diff --git a/supporting-blog-content/your-first-elastic-agent/Your_First_Elastic_Agent.ipynb b/supporting-blog-content/your-first-elastic-agent/Your_First_Elastic_Agent.ipynb new file mode 100644 index 00000000..1c2cc3f9 --- /dev/null +++ b/supporting-blog-content/your-first-elastic-agent/Your_First_Elastic_Agent.ipynb @@ -0,0 +1,4590 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Your First Elastic Agent\n", + "\n", + "This notebook is the API-driven companion to the blog post, **\"Your First Elastic Agent: From a Single Query to an AI-Powered Chat.\"**\n", + "\n", + "Here, we'll perform every step from the article—creating a tool, building an agent, and having a conversation—using Python to interact directly with the Agent Builder APIs.\n", + "\n", + "### Prerequisites\n", + "\n", + "To run this notebook, you will need:\n", + "* An active Elastic Cloud Serverless Project.\n", + " * You can sign up for a free trial at [Elastic Cloud Trial Page](https://cloud.elastic.co/trial)\n", + " * Create an `Elasticsearch` type project\n", + "* The URLs for both Elasticsearch and Kibana\n", + " * [How to get ES URL](https://www.elastic.co/docs/solutions/search/search-connection-details#find-cloud-id-serverless)\n", + " * For kibana, replace `.es.` in the url with `.kb.` in the ES URL\n", + "* An API Key with `write` permissions for Elasticsearch and Kibana (same API Key.\n", + " * [Doc page showing how to create API Key](https://www.elastic.co/docs/deploy-manage/api-keys/serverless-project-api-keys)" + ], + "metadata": { + "id": "c4XFmWJ1qLdO" + } + }, + { + "cell_type": "code", + "source": [ + "import os\n", + "\n", + "# Elasticsearch URL\n", + "es_url = input(\"Enter your Elasticsearch Endpoint URL: \")\n", + "# Kibana URL\n", + "kb_url = es_url.replace(\".es.\", \".kb.\")\n", + "# Elastic API Key\n", + "es_api_key = input(\"Enter your Elasticsearch API Key: \")\n", + "\n", + "print(\"Using connection details:\")\n", + "print(f\"Elasticsearch URL: {es_url}\")\n", + "print(f\"Kibana URL: {kb_url}\")\n", + "print(f\"ES_API_KEY: ***************************{es_api_key[-5:]}\")" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "PRYlw3dvxfvH", + "outputId": "432d5921-58a1-4e5f-d962-694bf68e7e96" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Enter your Elasticsearch Endpoint URL: https://your-first-elastic-agent-a4dc2b.es.us-central1.gcp.elastic.cloud:443\n", + "Enter your Elasticsearch API Key: bmU3SGRKa0JJdGhRdS1VdGJ5STg6a0ViYkZKcXA5ekx6LWNEZkR2TGxvZw==\n", + "Using connection details:\n", + "Elasticsearch URL: https://your-first-elastic-agent-a4dc2b.es.us-central1.gcp.elastic.cloud:443\n", + "Kibana URL: https://your-first-elastic-agent-a4dc2b.kb.us-central1.gcp.elastic.cloud:443\n", + "ES_API_KEY: ***************************vZw==\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Load Financial Data\n", + "This section will load synthetic financial data into your Elastic project for use demoing:\n", + "- Tool creation\n", + "- Agent creation\n", + "- Using the agent with the converse api\n", + "\n", + "If you have previously loaded the data you can skip this part.\n", + "\n", + "If you want to use other data, you will have to adjust the ES|QL queries to match the fields you have, as well as adjust the agent prompt and conversation questions to match your data\n" + ], + "metadata": { + "id": "YvJuXIbQ2IqL" + } + }, + { + "cell_type": "code", + "source": [ + "# Clone the repo\n", + "!git clone https://github.com/jeffvestal/synthetic-financial-data\n", + "%cd synthetic-financial-data" + ], + "metadata": { + "id": "_5sEty6RE3J4", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "7d72e2aa-99fc-4424-8cd9-0b8b27a8cb39" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Cloning into 'synthetic-financial-data'...\n", + "remote: Enumerating objects: 368, done.\u001b[K\n", + "remote: Counting objects: 100% (95/95), done.\u001b[K\n", + "remote: Compressing objects: 100% (70/70), done.\u001b[K\n", + "remote: Total 368 (delta 27), reused 72 (delta 20), pack-reused 273 (from 1)\u001b[K\n", + "Receiving objects: 100% (368/368), 19.93 MiB | 13.48 MiB/s, done.\n", + "Resolving deltas: 100% (199/199), done.\n", + "/content/synthetic-financial-data\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Install the python requirements to run the data loading script\n", + "!pip3 install -qr requirements.txt\n", + "!pip3 install -qr pandas" + ], + "metadata": { + "id": "DEN3VIC0TqHO", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "f90245d7-5ead-4bb0-9cd9-8db6e57473e2" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/937.5 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[91m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[91m╸\u001b[0m \u001b[32m931.8/937.5 kB\u001b[0m \u001b[31m47.8 MB/s\u001b[0m eta \u001b[36m0:00:01\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m937.5/937.5 kB\u001b[0m \u001b[31m25.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25h\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/2.0 MB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m68.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25h\u001b[?25l \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m0.0/65.1 kB\u001b[0m \u001b[31m?\u001b[0m eta \u001b[36m-:--:--\u001b[0m\r\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m65.1/65.1 kB\u001b[0m \u001b[31m4.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25h" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Wait until `.elser-2-elasticsearch` embedding inference endpoint is deployed and ready\n", + "import time, requests, os\n", + "\n", + "# Define request details\n", + "headers = {\"Authorization\": f\"ApiKey {es_api_key}\", \"Content-Type\": \"application/json\"}\n", + "url = f\"{es_url}/_inference/sparse_embedding/.elser-2-elasticsearch\"\n", + "attempt = 0\n", + "\n", + "# --- Main Check Loop ---\n", + "while True:\n", + " attempt += 1\n", + " print(f\"Polling endpoint... (Attempt #{attempt})\")\n", + "\n", + " try:\n", + " # Attempt to connect and raise an exception on failure\n", + " requests.post(\n", + " url, headers=headers, json={\"input\": \"test\"}, timeout=15\n", + " ).raise_for_status()\n", + " print(f\"✅ Endpoint is ready.\")\n", + " break # <-- Exit the loop on success\n", + "\n", + " except requests.exceptions.RequestException as e:\n", + " status = (\n", + " e.response.status_code if e.response is not None else \"N/A\"\n", + " ) # Modified line\n", + " if e.response is not None and 400 <= status < 500: # Modified line\n", + " # Exit immediately on client errors (e.g., 404 Not Found, 401 Unauthorized)\n", + " exit(\n", + " f\"❌ Client error ({status}). This is likely a permanent issue. Halting.\"\n", + " )\n", + "\n", + " # On any other error (e.g., 503 Service Unavailable), wait and retry\n", + " time.sleep(10)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "iMwxERhptQaL", + "outputId": "da756f9e-f8d0-475a-fd72-dda4105ced47" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Polling endpoint... (Attempt #1)\n", + "✅ Endpoint is ready.\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Load existing data to Elasticsearch. Set timestamps to now\n", + "\n", + "os.environ[\"ES_ENDPOINT_URL\"] = es_url\n", + "os.environ[\"ES_API_KEY\"] = es_api_key\n", + "!python3 load_all_data.py" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "LKSxziXAaBbn", + "outputId": "38d33284-ea31-4a4c-c49b-dd51e16d0c49" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "\n", + "============================================================\n", + "🚀 FAST DATA LOADER - ALL INDICES\n", + "============================================================\n", + "Settings: 1000 batch, 24 workers, timestamps→now\n", + "Time: 2025-09-23 04:29:02\n", + "============================================================\n", + "\n", + "/usr/local/lib/python3.12/dist-packages/elasticsearch/_sync/client/__init__.py:311: SecurityWarning: Connecting to 'https://your-first-elastic-agent-a4dc2b.es.us-central1.gcp.elastic.cloud:443' using TLS with verify_certs=False is insecure\n", + " _transport = transport_class(\n", + "Elasticsearch client initialized successfully.\n", + "✓ Connected to Elasticsearch\n", + "\n", + " 📁 Accounts: 7,000 documents\n", + " 📁 Holdings: 122,923 documents\n", + " 📁 Assets: 183 documents\n", + " 📁 News: 550 documents\n", + " 📁 Reports: 120 documents\n", + "\n", + "📊 Total: 130,776 documents across 5 indices\n", + "============================================================\n", + "\n", + "⏳ Loading Accounts...Starting: financial_accounts (workers: 24, updating timestamps to current time)\n", + "Starting: financial_accounts (workers: 24, updating timestamps to current time)\n", + "Creating index 'financial_accounts'...\n", + "✓ Successfully created index 'financial_accounts'\n", + " Updating timestamps to: 2025-09-23T04:29:03\n", + "[04:29:05] financial_accounts: batch 1/7 complete (1000 docs, 1000 total)\n", + "[04:29:05] financial_accounts: batch 2/7 complete (1000 docs, 2000 total)\n", + "[04:29:05] financial_accounts: batch 3/7 complete (1000 docs, 3000 total)\n", + "[04:29:05] financial_accounts: batch 4/7 complete (1000 docs, 4000 total)\n", + "[04:29:05] financial_accounts: batch 5/7 complete (1000 docs, 5000 total)\n", + "[04:29:05] financial_accounts: batch 6/7 complete (1000 docs, 6000 total)\n", + "[04:29:05] financial_accounts: batch 7/7 complete (1000 docs, 7000 total)\n", + " ✓ 2.9s (2439 docs/sec)\n", + "\n", + "⏳ Loading Holdings...Starting: financial_holdings (workers: 24, updating timestamps to current time)\n", + "Starting: financial_holdings (workers: 24, updating timestamps to current time)\n", + "Creating index 'financial_holdings'...\n", + "✓ Successfully created index 'financial_holdings'\n", + " Updating timestamps to: 2025-09-23T04:29:06\n", + "[04:29:09] financial_holdings: batch 1/123 complete (1000 docs, 1000 total)\n", + "[04:29:09] financial_holdings: batch 2/123 complete (1000 docs, 2000 total)\n", + "[04:29:09] financial_holdings: batch 3/123 complete (1000 docs, 3000 total)\n", + "[04:29:09] financial_holdings: batch 4/123 complete (1000 docs, 4000 total)\n", + "[04:29:09] financial_holdings: batch 5/123 complete (1000 docs, 5000 total)\n", + "[04:29:09] financial_holdings: batch 6/123 complete (1000 docs, 6000 total)\n", + "[04:29:09] financial_holdings: batch 7/123 complete (1000 docs, 7000 total)\n", + "[04:29:10] financial_holdings: batch 8/123 complete (1000 docs, 8000 total)\n", + "[04:29:10] financial_holdings: batch 9/123 complete (1000 docs, 9000 total)\n", + "[04:29:10] financial_holdings: batch 10/123 complete (1000 docs, 10000 total)\n", + "[04:29:10] financial_holdings: batch 11/123 complete (1000 docs, 11000 total)\n", + "[04:29:10] financial_holdings: batch 12/123 complete (1000 docs, 12000 total)\n", + "[04:29:10] financial_holdings: batch 13/123 complete (1000 docs, 13000 total)\n", + "[04:29:10] financial_holdings: batch 14/123 complete (1000 docs, 14000 total)\n", + "[04:29:10] financial_holdings: batch 15/123 complete (1000 docs, 15000 total)\n", + "[04:29:10] financial_holdings: batch 16/123 complete (1000 docs, 16000 total)\n", + "[04:29:10] financial_holdings: batch 17/123 complete (1000 docs, 17000 total)\n", + "[04:29:10] financial_holdings: batch 18/123 complete (1000 docs, 18000 total)\n", + "[04:29:10] financial_holdings: batch 19/123 complete (1000 docs, 19000 total)\n", + "[04:29:11] financial_holdings: batch 20/123 complete (1000 docs, 20000 total)\n", + "[04:29:11] financial_holdings: batch 21/123 complete (1000 docs, 21000 total)\n", + "[04:29:11] financial_holdings: batch 22/123 complete (1000 docs, 22000 total)\n", + "[04:29:11] financial_holdings: batch 23/123 complete (1000 docs, 23000 total)\n", + "[04:29:11] financial_holdings: batch 24/123 complete (1000 docs, 24000 total)\n", + "[04:29:11] financial_holdings: batch 25/123 complete (1000 docs, 25000 total)\n", + "[04:29:11] financial_holdings: batch 26/123 complete (1000 docs, 26000 total)\n", + "[04:29:11] financial_holdings: batch 27/123 complete (1000 docs, 27000 total)\n", + "[04:29:11] financial_holdings: batch 28/123 complete (1000 docs, 28000 total)\n", + "[04:29:11] financial_holdings: batch 29/123 complete (1000 docs, 29000 total)\n", + "[04:29:11] financial_holdings: batch 30/123 complete (1000 docs, 30000 total)\n", + "[04:29:11] financial_holdings: batch 31/123 complete (1000 docs, 31000 total)\n", + "[04:29:11] financial_holdings: batch 32/123 complete (1000 docs, 32000 total)\n", + "[04:29:11] financial_holdings: batch 33/123 complete (1000 docs, 33000 total)\n", + "[04:29:12] financial_holdings: batch 34/123 complete (1000 docs, 34000 total)\n", + "[04:29:12] financial_holdings: batch 35/123 complete (1000 docs, 35000 total)\n", + "[04:29:12] financial_holdings: batch 36/123 complete (1000 docs, 36000 total)\n", + "[04:29:12] financial_holdings: batch 37/123 complete (1000 docs, 37000 total)\n", + "[04:29:12] financial_holdings: batch 38/123 complete (1000 docs, 38000 total)\n", + "[04:29:12] financial_holdings: batch 39/123 complete (1000 docs, 39000 total)\n", + "[04:29:12] financial_holdings: batch 40/123 complete (1000 docs, 40000 total)\n", + "[04:29:12] financial_holdings: batch 41/123 complete (1000 docs, 41000 total)\n", + "[04:29:12] financial_holdings: batch 42/123 complete (1000 docs, 42000 total)\n", + "[04:29:12] financial_holdings: batch 43/123 complete (1000 docs, 43000 total)\n", + "[04:29:12] financial_holdings: batch 44/123 complete (1000 docs, 44000 total)\n", + "[04:29:12] financial_holdings: batch 45/123 complete (1000 docs, 45000 total)\n", + "[04:29:12] financial_holdings: batch 46/123 complete (1000 docs, 46000 total)\n", + "[04:29:13] financial_holdings: batch 47/123 complete (1000 docs, 47000 total)\n", + "[04:29:13] financial_holdings: batch 48/123 complete (1000 docs, 48000 total)\n", + "[04:29:13] financial_holdings: batch 49/123 complete (1000 docs, 49000 total)\n", + "[04:29:13] financial_holdings: batch 50/123 complete (1000 docs, 50000 total)\n", + "[04:29:13] financial_holdings: batch 51/123 complete (1000 docs, 51000 total)\n", + "[04:29:13] financial_holdings: batch 52/123 complete (1000 docs, 52000 total)\n", + "[04:29:13] financial_holdings: batch 53/123 complete (1000 docs, 53000 total)\n", + "[04:29:13] financial_holdings: batch 54/123 complete (1000 docs, 54000 total)\n", + "[04:29:13] financial_holdings: batch 55/123 complete (1000 docs, 55000 total)\n", + "[04:29:13] financial_holdings: batch 56/123 complete (1000 docs, 56000 total)\n", + "[04:29:13] financial_holdings: batch 57/123 complete (1000 docs, 57000 total)\n", + "[04:29:13] financial_holdings: batch 58/123 complete (1000 docs, 58000 total)\n", + "[04:29:13] financial_holdings: batch 59/123 complete (1000 docs, 59000 total)\n", + "[04:29:14] financial_holdings: batch 60/123 complete (1000 docs, 60000 total)\n", + "[04:29:14] financial_holdings: batch 61/123 complete (1000 docs, 61000 total)\n", + "[04:29:14] financial_holdings: batch 62/123 complete (1000 docs, 62000 total)\n", + "[04:29:14] financial_holdings: batch 63/123 complete (1000 docs, 63000 total)\n", + "[04:29:14] financial_holdings: batch 64/123 complete (1000 docs, 64000 total)\n", + "[04:29:14] financial_holdings: batch 65/123 complete (1000 docs, 65000 total)\n", + "[04:29:14] financial_holdings: batch 66/123 complete (1000 docs, 66000 total)\n", + "[04:29:14] financial_holdings: batch 67/123 complete (1000 docs, 67000 total)\n", + "[04:29:14] financial_holdings: batch 68/123 complete (1000 docs, 68000 total)\n", + "[04:29:14] financial_holdings: batch 69/123 complete (1000 docs, 69000 total)\n", + "[04:29:14] financial_holdings: batch 70/123 complete (1000 docs, 70000 total)\n", + "[04:29:14] financial_holdings: batch 71/123 complete (1000 docs, 71000 total)\n", + "[04:29:14] financial_holdings: batch 72/123 complete (1000 docs, 72000 total)\n", + "[04:29:14] financial_holdings: batch 73/123 complete (1000 docs, 73000 total)\n", + "[04:29:14] financial_holdings: batch 74/123 complete (1000 docs, 74000 total)\n", + "[04:29:14] financial_holdings: batch 75/123 complete (1000 docs, 75000 total)\n", + "[04:29:14] financial_holdings: batch 76/123 complete (1000 docs, 76000 total)\n", + "[04:29:14] financial_holdings: batch 77/123 complete (1000 docs, 77000 total)\n", + "[04:29:15] financial_holdings: batch 78/123 complete (1000 docs, 78000 total)\n", + "[04:29:15] financial_holdings: batch 79/123 complete (1000 docs, 79000 total)\n", + "[04:29:15] financial_holdings: batch 80/123 complete (1000 docs, 80000 total)\n", + "[04:29:15] financial_holdings: batch 81/123 complete (1000 docs, 81000 total)\n", + "[04:29:15] financial_holdings: batch 82/123 complete (1000 docs, 82000 total)\n", + "[04:29:15] financial_holdings: batch 83/123 complete (1000 docs, 83000 total)\n", + "[04:29:15] financial_holdings: batch 84/123 complete (1000 docs, 84000 total)\n", + "[04:29:15] financial_holdings: batch 85/123 complete (1000 docs, 85000 total)\n", + "[04:29:15] financial_holdings: batch 86/123 complete (1000 docs, 86000 total)\n", + "[04:29:15] financial_holdings: batch 87/123 complete (1000 docs, 87000 total)\n", + "[04:29:15] financial_holdings: batch 88/123 complete (1000 docs, 88000 total)\n", + "[04:29:15] financial_holdings: batch 89/123 complete (1000 docs, 89000 total)\n", + "[04:29:16] financial_holdings: batch 90/123 complete (1000 docs, 90000 total)\n", + "[04:29:16] financial_holdings: batch 91/123 complete (1000 docs, 91000 total)\n", + "[04:29:16] financial_holdings: batch 92/123 complete (1000 docs, 92000 total)\n", + "[04:29:16] financial_holdings: batch 93/123 complete (1000 docs, 93000 total)\n", + "[04:29:16] financial_holdings: batch 94/123 complete (1000 docs, 94000 total)\n", + "[04:29:16] financial_holdings: batch 95/123 complete (1000 docs, 95000 total)\n", + "[04:29:16] financial_holdings: batch 96/123 complete (1000 docs, 96000 total)\n", + "[04:29:16] financial_holdings: batch 97/123 complete (1000 docs, 97000 total)\n", + "[04:29:16] financial_holdings: batch 98/123 complete (1000 docs, 98000 total)\n", + "[04:29:16] financial_holdings: batch 99/123 complete (1000 docs, 99000 total)\n", + "[04:29:16] financial_holdings: batch 100/123 complete (1000 docs, 100000 total)\n", + "[04:29:16] financial_holdings: batch 101/123 complete (1000 docs, 101000 total)\n", + "[04:29:16] financial_holdings: batch 102/123 complete (1000 docs, 102000 total)\n", + "[04:29:16] financial_holdings: batch 103/123 complete (1000 docs, 103000 total)\n", + "[04:29:16] financial_holdings: batch 104/123 complete (1000 docs, 104000 total)\n", + "[04:29:16] financial_holdings: batch 105/123 complete (1000 docs, 105000 total)\n", + "[04:29:16] financial_holdings: batch 106/123 complete (1000 docs, 106000 total)\n", + "[04:29:16] financial_holdings: batch 107/123 complete (1000 docs, 107000 total)\n", + "[04:29:17] financial_holdings: batch 108/123 complete (1000 docs, 108000 total)\n", + "[04:29:17] financial_holdings: batch 109/123 complete (1000 docs, 109000 total)\n", + "[04:29:17] financial_holdings: batch 110/123 complete (1000 docs, 110000 total)\n", + "[04:29:17] financial_holdings: batch 111/123 complete (1000 docs, 111000 total)\n", + "[04:29:17] financial_holdings: batch 112/123 complete (1000 docs, 112000 total)\n", + "[04:29:17] financial_holdings: batch 113/123 complete (1000 docs, 113000 total)\n", + "[04:29:17] financial_holdings: batch 114/123 complete (1000 docs, 114000 total)\n", + "[04:29:17] financial_holdings: batch 115/123 complete (1000 docs, 115000 total)\n", + "[04:29:17] financial_holdings: batch 116/123 complete (1000 docs, 116000 total)\n", + "[04:29:17] financial_holdings: batch 117/123 complete (1000 docs, 117000 total)\n", + "[04:29:17] financial_holdings: batch 118/123 complete (1000 docs, 118000 total)\n", + "[04:29:17] financial_holdings: batch 119/123 complete (1000 docs, 119000 total)\n", + "[04:29:17] financial_holdings: batch 120/123 complete (1000 docs, 120000 total)\n", + "[04:29:17] financial_holdings: batch 121/123 complete (923 docs, 120923 total)\n", + "[04:29:17] financial_holdings: batch 122/123 complete (1000 docs, 121923 total)\n", + "[04:29:17] financial_holdings: batch 123/123 complete (1000 docs, 122923 total)\n", + " ✓ 12.4s (9899 docs/sec)\n", + "\n", + "⏳ Loading Assets...Starting: financial_asset_details (workers: 24, updating timestamps to current time)\n", + "Starting: financial_asset_details (workers: 24, updating timestamps to current time)\n", + "Creating index 'financial_asset_details'...\n", + "✓ Successfully created index 'financial_asset_details'\n", + " Updating timestamps to: 2025-09-23T04:29:18\n", + "[04:29:28] financial_asset_details: batch 1/1 complete (183 docs, 183 total)\n", + " ✓ 10.6s (17 docs/sec)\n", + "\n", + "⏳ Loading News...Starting: financial_news (workers: 24, updating timestamps to current time)\n", + "Starting: financial_news (workers: 24, updating timestamps to current time)\n", + "Creating index 'financial_news'...\n", + "✓ Successfully created index 'financial_news'\n", + " Updating timestamps to: 2025-09-23T04:29:29\n", + "[04:30:30] financial_news: batch 1/1 FAILED\n", + " ✓ 61.6s (9 docs/sec)\n", + "\n", + "⏳ Loading Reports...Starting: financial_reports (workers: 24, updating timestamps to current time)\n", + "Starting: financial_reports (workers: 24, updating timestamps to current time)\n", + "Creating index 'financial_reports'...\n", + "✓ Successfully created index 'financial_reports'\n", + " Updating timestamps to: 2025-09-23T04:30:31\n", + "[04:31:31] financial_reports: batch 1/1 FAILED\n", + " ✓ 61.6s (2 docs/sec)\n", + "\n", + "============================================================\n", + "✅ COMPLETE: 5/5 indices loaded\n", + "⏱️ Total time: 149.1 seconds\n", + "📈 Average: 877 docs/second\n", + "🕐 Finished: 04:31:31\n", + "============================================================\n", + "\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Check incices are setup and data was loaded\n", + "!python3 control.py --check-indices" + ], + "metadata": { + "id": "Ov8po55vTltt", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "5e271ca7-0a2f-4c93-c064-7ca14ea189a1" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "🚀 \u001b[34mRunning in non-interactive mode\u001b[0m\u001b[34m...\u001b[0m\n", + "🔍 \u001b[34mConnecting to Elasticsearch\u001b[0m\u001b[34m...\u001b[0m\n", + "/usr/local/lib/python3.12/dist-packages/elasticsearch/_sync/client/__init__.py:311: SecurityWarning: Connecting to 'https://your-first-elastic-agent-a4dc2b.es.us-central1.gcp.elastic.cloud:443' using TLS with verify_certs=False is insecure\n", + " _transport = transport_class(\n", + "Elasticsearch client initialized successfully.\n", + "✅ \u001b[32mConnected to Elasticsearch \u001b[0m\u001b[1;32m8.11\u001b[0m\u001b[32m.\u001b[0m\u001b[1;32m0\u001b[0m\n", + "\n", + "\u001b[3m 📊 Index Status Summary \u001b[0m\n", + "┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n", + "┃\u001b[1m \u001b[0m\u001b[1mIndex Name \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mExi…\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mDocum…\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Size\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mErrors \u001b[0m\u001b[1m \u001b[0m┃\n", + "┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩\n", + "│\u001b[36m \u001b[0m\u001b[36mfinancial_asset_deta…\u001b[0m\u001b[36m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m✓ \u001b[0m\u001b[37m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m 183\u001b[0m\u001b[37m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m N/A\u001b[0m\u001b[37m \u001b[0m│\u001b[31m \u001b[0m\u001b[31m \u001b[0m\u001b[31m \u001b[0m│\n", + "│\u001b[36m \u001b[0m\u001b[36mfinancial_accounts \u001b[0m\u001b[36m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m✓ \u001b[0m\u001b[37m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m 7,000\u001b[0m\u001b[37m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m N/A\u001b[0m\u001b[37m \u001b[0m│\u001b[31m \u001b[0m\u001b[31m \u001b[0m\u001b[31m \u001b[0m│\n", + "│\u001b[36m \u001b[0m\u001b[36mfinancial_holdings \u001b[0m\u001b[36m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m✓ \u001b[0m\u001b[37m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m122,9…\u001b[0m\u001b[37m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m N/A\u001b[0m\u001b[37m \u001b[0m│\u001b[31m \u001b[0m\u001b[31m \u001b[0m\u001b[31m \u001b[0m│\n", + "│\u001b[36m \u001b[0m\u001b[36mfinancial_news \u001b[0m\u001b[36m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m✓ \u001b[0m\u001b[37m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m 550\u001b[0m\u001b[37m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m N/A\u001b[0m\u001b[37m \u001b[0m│\u001b[31m \u001b[0m\u001b[31m \u001b[0m\u001b[31m \u001b[0m│\n", + "│\u001b[36m \u001b[0m\u001b[36mfinancial_reports \u001b[0m\u001b[36m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m✓ \u001b[0m\u001b[37m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m 120\u001b[0m\u001b[37m \u001b[0m│\u001b[37m \u001b[0m\u001b[37m N/A\u001b[0m\u001b[37m \u001b[0m│\u001b[31m \u001b[0m\u001b[31m \u001b[0m\u001b[31m \u001b[0m│\n", + "└───────────────────────┴──────┴────────┴────────┴─────────────────────────────┘\n", + "\n", + "\u001b[32m✓ All \u001b[0m\u001b[1;32m5\u001b[0m\u001b[32m indices are properly configured\u001b[0m\n", + "\u001b[2mTotal: \u001b[0m\u001b[1;2;36m130\u001b[0m\u001b[2m,\u001b[0m\u001b[1;2;36m776\u001b[0m\u001b[2m documents \u001b[0m\u001b[1;2m(\u001b[0m\u001b[2msize not available in serverless\u001b[0m\u001b[1;2m)\u001b[0m\n", + "\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Kibana Setup for Agent Builder" + ], + "metadata": { + "id": "pUZLUZ6y2gGg" + } + }, + { + "cell_type": "code", + "source": [ + "# Import necessary libraries\n", + "import os\n", + "import json\n", + "import requests\n", + "from getpass import getpass # To securely ask for the API key\n", + "from IPython.display import display, Markdown, JSON\n", + "\n", + "# --- Setup Headers ---\n", + "HEADERS = {\n", + " \"Content-Type\": \"application/json\",\n", + " \"kbn-xsrf\": \"true\",\n", + " \"Authorization\": f\"ApiKey {es_api_key}\",\n", + "}\n", + "\n", + "# --- Verify Connection ---\n", + "# Let's make a simple call to the root endpoint to verify our connection and credentials.\n", + "if not kb_url:\n", + " print(\"⚠️ KIBANA_ENDPOINT was not provided. Please provide the endpoint URL.\")\n", + "else:\n", + " try:\n", + " response = requests.get(kb_url + \"/api/status\", headers=HEADERS)\n", + " response.raise_for_status() # Raises an exception for bad status codes (4xx or 5xx)\n", + "\n", + " status = response.json()\n", + " cluster_name = status.get(\"name\")\n", + " version = status.get(\"version\").get(\"number\")\n", + "\n", + " print(f\"✅ Successfully connected to Kibana!\")\n", + " print(f\"Cluster Name: {cluster_name}\")\n", + " print(f\"Version: {version}\")\n", + "\n", + " except requests.exceptions.RequestException as e:\n", + " print(f\"❌ Connection Failed: {e}\")" + ], + "metadata": { + "id": "4yz3J4_DqMps", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "e64b06f4-4c65-455c-e545-03736f848231" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ Successfully connected to Kibana!\n", + "Cluster Name: kb\n", + "Version: 9.2.0\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "#ONLY BEFORE PUBLIC PREVIEW:\n", + "You will need to enable Agent Builder in your project.\n", + "\n", + "Do to this\n", + "1. Navigate to `Developer Tools` in Kibana\n", + "2. Run the following command\n", + " ```\n", + " POST kbn://internal/kibana/settings\n", + " {\n", + " \"changes\": {\n", + " \"agentBuilder:enabled\": true\n", + " }\n", + " }\n", + " ```\n", + "3. Refresh your browser\n", + "\n", + "You should now see `Agents` in the navigation side bar\n", + "\n", + "\n", + "![CleanShot 2025-09-23 at 10.33.07@2x.png](data:image/png;base64,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)\n" + ], + "metadata": { + "id": "IuYaDvcT75d1" + } + }, + { + "cell_type": "markdown", + "source": [ + "# Section 1: The Logic - Testing the ES|QL Query\n", + "\n", + "Before we register our logic as a persistent Tool, it's a best practice to test the raw ES|QL query first. This allows us to validate the syntax and confirm it returns the data we expect. We'll use the `/_query` endpoint for this." + ], + "metadata": { + "id": "2D2afJeHqUYz" + } + }, + { + "cell_type": "code", + "source": [ + "# First, let's define our multi-line ES|QL query in a Python string.\n", + "# This is the same query that will eventually power our custom tool.\n", + "\n", + "esql_query = \"\"\"\n", + "FROM financial_news, financial_reports METADATA _index\n", + " | WHERE sentiment == \"negative\"\n", + " | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(?time_duration)\n", + " | RENAME primary_symbol AS symbol\n", + " | LOOKUP JOIN financial_asset_details ON symbol\n", + " | LOOKUP JOIN financial_holdings ON symbol\n", + " | LOOKUP JOIN financial_accounts ON account_id\n", + " | WHERE account_holder_name IS NOT NULL\n", + " | EVAL position_current_value = quantity * current_price.price\n", + " | RENAME title AS news_title\n", + " | KEEP\n", + " account_holder_name, symbol, asset_name, news_title,\n", + " sentiment, position_current_value, quantity, current_price.price,\n", + " published_date, report_date\n", + " | SORT position_current_value DESC\n", + " | LIMIT 50\n", + "\"\"\"\n", + "\n", + "print(\"✅ ES|QL query string is defined.\")" + ], + "metadata": { + "id": "Yij22M9Iqize", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "c0caff64-f89a-40f9-dca4-095278120b20" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ ES|QL query string is defined.\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Now, we'll construct the JSON body for the API request.\n", + "# The `params` object is where we provide values for the placeholders in our query string.\n", + "\n", + "request_body = {\"query\": esql_query, \"params\": [{\"time_duration\": \"2000 hours\"}]}\n", + "\n", + "print(\"✅ Request body is defined with test parameters:\")\n", + "print(json.dumps(request_body, indent=2))" + ], + "metadata": { + "id": "zJNSVYJhqmNb", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "f78f9d9d-5905-4b12-e3bc-b94e9bc17ed0" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ Request body is defined with test parameters:\n", + "{\n", + " \"query\": \"\\nFROM financial_news, financial_reports METADATA _index\\n | WHERE sentiment == \\\"negative\\\"\\n | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(?time_duration)\\n | RENAME primary_symbol AS symbol\\n | LOOKUP JOIN financial_asset_details ON symbol\\n | LOOKUP JOIN financial_holdings ON symbol\\n | LOOKUP JOIN financial_accounts ON account_id\\n | WHERE account_holder_name IS NOT NULL\\n | EVAL position_current_value = quantity * current_price.price\\n | RENAME title AS news_title\\n | KEEP\\n account_holder_name, symbol, asset_name, news_title,\\n sentiment, position_current_value, quantity, current_price.price,\\n published_date, report_date\\n | SORT position_current_value DESC\\n | LIMIT 50\\n\",\n", + " \"params\": [\n", + " {\n", + " \"time_duration\": \"2000 hours\"\n", + " }\n", + " ]\n", + "}\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Finally, let's execute the query and display the results in a clean table using pandas.\n", + "import pandas as pd\n", + "\n", + "# display(Markdown(f\"### 🧪 Testing Query for Symbol: `{request_body['params'][1]['symbol']}`\"))\n", + "\n", + "try:\n", + " # We use the /_query endpoint to run a raw ES|QL query\n", + " response = requests.post(f\"{es_url}/_query\", headers=HEADERS, json=request_body)\n", + " response.raise_for_status()\n", + "\n", + " # The response contains column names and rows of values\n", + " query_result = response.json()\n", + " columns = [col[\"name\"] for col in query_result[\"columns\"]]\n", + " # Check for 'values' key if 'rows' is not present\n", + " rows = query_result.get(\"rows\", query_result.get(\"values\", []))\n", + "\n", + " # Create and display a pandas DataFrame for a clean table view\n", + " df = pd.DataFrame(rows, columns=columns)\n", + " display(df)\n", + "\n", + "except requests.exceptions.RequestException as e:\n", + " print(f\"❌ Query Failed: {e.response.text}\")\n", + "except KeyError:\n", + " print(\"❌ Query executed, but the response format was unexpected.\")\n", + " print(\"Raw response:\")\n", + " print(response.json())\n", + " raise" + ], + "metadata": { + "id": "F5KCf1E-qpu2", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + }, + "outputId": "323408ef-59b4-4d78-d9db-9a8ad21d111f" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + " account_holder_name symbol asset_name \\\n", + "0 Victoria Schneider TXN Texas Instruments Inc. \n", + "1 Lorraine Gibson TXN Texas Instruments Inc. \n", + "2 Jillian Davis TXN Texas Instruments Inc. \n", + "3 Craig Griffith TXN Texas Instruments Inc. \n", + "4 Jeffrey Byrd TXN Texas Instruments Inc. \n", + "5 Patrick Rice TXN Texas Instruments Inc. \n", + "6 Sophia Dean TXN Texas Instruments Inc. \n", + "7 Sandra Nunez TXN Texas Instruments Inc. \n", + "8 Brandon Esparza TXN Texas Instruments Inc. \n", + "9 Miranda Vargas TXN Texas Instruments Inc. \n", + "10 Eileen Bailey TXN Texas Instruments Inc. \n", + "11 Misty Gonzalez TXN Texas Instruments Inc. \n", + "12 Briana Mcclure TXN Texas Instruments Inc. \n", + "13 James Miller TXN Texas Instruments Inc. \n", + "14 Reginald Wang TXN Texas Instruments Inc. \n", + "15 Devin Hernandez TXN Texas Instruments Inc. \n", + "16 Meghan Parker TXN Texas Instruments Inc. \n", + "17 Lindsay Harris TXN Texas Instruments Inc. \n", + "18 Jonathan Sullivan TXN Texas Instruments Inc. \n", + "19 Stephanie Sosa TXN Texas Instruments Inc. \n", + "20 Nicole Smith TXN Texas Instruments Inc. \n", + "21 Jamie Allen TXN Texas Instruments Inc. \n", + "22 Sharon Brown TXN Texas Instruments Inc. \n", + "23 Terry Welch TXN Texas Instruments Inc. \n", + "24 Joshua Shaw TXN Texas Instruments Inc. \n", + "25 Clinton Greene TXN Texas Instruments Inc. \n", + "26 Karen Fisher TXN Texas Instruments Inc. \n", + "27 Angela Horn TXN Texas Instruments Inc. \n", + "28 Tracy Chambers GM General Motors Co. \n", + "29 Tonya Bush GM General Motors Co. \n", + "30 Lauren Hatfield GM General Motors Co. \n", + "31 Cynthia Harris TXN Texas Instruments Inc. \n", + "32 David Torres TXN Texas Instruments Inc. \n", + "33 Stacy Ellis GM General Motors Co. \n", + "34 Jason Hill TXN Texas Instruments Inc. \n", + "35 James Edwards GM General Motors Co. \n", + "36 Douglas Perry GM General Motors Co. \n", + "37 Amanda Fuller TXN Texas Instruments Inc. \n", + "38 Crystal Reed TXN Texas Instruments Inc. \n", + "39 Amber Hernandez GM General Motors Co. \n", + "40 Madison Harper GM General Motors Co. \n", + "41 Rebecca Bradley TXN Texas Instruments Inc. \n", + "42 Tiffany Walters GM General Motors Co. \n", + "43 Tracy Thomas GM General Motors Co. \n", + "44 Jose Marshall GM General Motors Co. \n", + "45 Robert Bennett TXN Texas Instruments Inc. \n", + "46 Sarah Scott TXN Texas Instruments Inc. \n", + "47 Hailey Thomas GM General Motors Co. \n", + "48 George Richard GM General Motors Co. \n", + "49 Ashley Walton GM General Motors Co. \n", + "\n", + " news_title sentiment \\\n", + "0 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "1 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "2 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "3 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "4 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "5 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "6 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "7 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "8 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "9 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "10 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "11 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "12 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "13 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "14 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "15 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "16 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "17 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "18 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "19 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "20 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "21 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "22 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "23 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "24 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "25 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "26 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "27 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "28 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "29 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "30 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "31 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "32 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "33 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "34 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "35 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "36 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "37 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "38 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "39 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "40 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "41 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "42 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "43 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "44 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "45 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "46 TXN Tumbles on Major Cybersecurity Breach, IP ... negative \n", + "47 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "48 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "49 GM Signals Trouble as Economic Slowdown Hits A... negative \n", + "\n", + " position_current_value quantity current_price.price \\\n", + "0 273680.004883 200.0 1368.400024 \n", + "1 272311.604858 199.0 1368.400024 \n", + "2 272311.604858 199.0 1368.400024 \n", + "3 272311.604858 199.0 1368.400024 \n", + "4 270943.204834 198.0 1368.400024 \n", + "5 270943.204834 198.0 1368.400024 \n", + "6 270943.204834 198.0 1368.400024 \n", + "7 269574.804810 197.0 1368.400024 \n", + "8 269574.804810 197.0 1368.400024 \n", + "9 269574.804810 197.0 1368.400024 \n", + "10 269574.804810 197.0 1368.400024 \n", + "11 269574.804810 197.0 1368.400024 \n", + "12 268206.404785 196.0 1368.400024 \n", + "13 268206.404785 196.0 1368.400024 \n", + "14 268206.404785 196.0 1368.400024 \n", + "15 266838.004761 195.0 1368.400024 \n", + "16 266838.004761 195.0 1368.400024 \n", + "17 266838.004761 195.0 1368.400024 \n", + "18 265469.604736 194.0 1368.400024 \n", + "19 264101.204712 193.0 1368.400024 \n", + "20 264101.204712 193.0 1368.400024 \n", + "21 264101.204712 193.0 1368.400024 \n", + "22 262732.804688 192.0 1368.400024 \n", + "23 262732.804688 192.0 1368.400024 \n", + "24 262732.804688 192.0 1368.400024 \n", + "25 261364.404663 191.0 1368.400024 \n", + "26 261364.404663 191.0 1368.400024 \n", + "27 261364.404663 191.0 1368.400024 \n", + "28 258719.995117 200.0 1293.599976 \n", + "29 258719.995117 200.0 1293.599976 \n", + "30 258719.995117 200.0 1293.599976 \n", + "31 258627.604614 189.0 1368.400024 \n", + "32 258627.604614 189.0 1368.400024 \n", + "33 257426.395142 199.0 1293.599976 \n", + "34 257259.204590 188.0 1368.400024 \n", + "35 256132.795166 198.0 1293.599976 \n", + "36 256132.795166 198.0 1293.599976 \n", + "37 255890.804565 187.0 1368.400024 \n", + "38 255890.804565 187.0 1368.400024 \n", + "39 254839.195190 197.0 1293.599976 \n", + "40 254839.195190 197.0 1293.599976 \n", + "41 253154.004517 185.0 1368.400024 \n", + "42 252251.995239 195.0 1293.599976 \n", + "43 252251.995239 195.0 1293.599976 \n", + "44 252251.995239 195.0 1293.599976 \n", + "45 251785.604492 184.0 1368.400024 \n", + "46 251785.604492 184.0 1368.400024 \n", + "47 250958.395264 194.0 1293.599976 \n", + "48 250958.395264 194.0 1293.599976 \n", + "49 250958.395264 194.0 1293.599976 \n", + "\n", + " published_date report_date \n", + "0 2025-09-23T04:29:29.000Z None \n", + "1 2025-09-23T04:29:29.000Z None \n", + "2 2025-09-23T04:29:29.000Z None \n", + "3 2025-09-23T04:29:29.000Z None \n", + "4 2025-09-23T04:29:29.000Z None \n", + "5 2025-09-23T04:29:29.000Z None \n", + "6 2025-09-23T04:29:29.000Z None \n", + "7 2025-09-23T04:29:29.000Z None \n", + "8 2025-09-23T04:29:29.000Z None \n", + "9 2025-09-23T04:29:29.000Z None \n", + "10 2025-09-23T04:29:29.000Z None \n", + "11 2025-09-23T04:29:29.000Z None \n", + "12 2025-09-23T04:29:29.000Z None \n", + "13 2025-09-23T04:29:29.000Z None \n", + "14 2025-09-23T04:29:29.000Z None \n", + "15 2025-09-23T04:29:29.000Z None \n", + "16 2025-09-23T04:29:29.000Z None \n", + "17 2025-09-23T04:29:29.000Z None \n", + "18 2025-09-23T04:29:29.000Z None \n", + "19 2025-09-23T04:29:29.000Z None \n", + "20 2025-09-23T04:29:29.000Z None \n", + "21 2025-09-23T04:29:29.000Z None \n", + "22 2025-09-23T04:29:29.000Z None \n", + "23 2025-09-23T04:29:29.000Z None \n", + "24 2025-09-23T04:29:29.000Z None \n", + "25 2025-09-23T04:29:29.000Z None \n", + "26 2025-09-23T04:29:29.000Z None \n", + "27 2025-09-23T04:29:29.000Z None \n", + "28 2025-09-23T04:29:29.000Z None \n", + "29 2025-09-23T04:29:29.000Z None \n", + "30 2025-09-23T04:29:29.000Z None \n", + "31 2025-09-23T04:29:29.000Z None \n", + "32 2025-09-23T04:29:29.000Z None \n", + "33 2025-09-23T04:29:29.000Z None \n", + "34 2025-09-23T04:29:29.000Z None \n", + "35 2025-09-23T04:29:29.000Z None \n", + "36 2025-09-23T04:29:29.000Z None \n", + "37 2025-09-23T04:29:29.000Z None \n", + "38 2025-09-23T04:29:29.000Z None \n", + "39 2025-09-23T04:29:29.000Z None \n", + "40 2025-09-23T04:29:29.000Z None \n", + "41 2025-09-23T04:29:29.000Z None \n", + "42 2025-09-23T04:29:29.000Z None \n", + "43 2025-09-23T04:29:29.000Z None \n", + "44 2025-09-23T04:29:29.000Z None \n", + "45 2025-09-23T04:29:29.000Z None \n", + "46 2025-09-23T04:29:29.000Z None \n", + "47 2025-09-23T04:29:29.000Z None \n", + "48 2025-09-23T04:29:29.000Z None \n", + "49 2025-09-23T04:29:29.000Z None " + ], + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
account_holder_namesymbolasset_namenews_titlesentimentposition_current_valuequantitycurrent_price.pricepublished_datereport_date
0Victoria SchneiderTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative273680.004883200.01368.4000242025-09-23T04:29:29.000ZNone
1Lorraine GibsonTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative272311.604858199.01368.4000242025-09-23T04:29:29.000ZNone
2Jillian DavisTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative272311.604858199.01368.4000242025-09-23T04:29:29.000ZNone
3Craig GriffithTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative272311.604858199.01368.4000242025-09-23T04:29:29.000ZNone
4Jeffrey ByrdTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative270943.204834198.01368.4000242025-09-23T04:29:29.000ZNone
5Patrick RiceTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative270943.204834198.01368.4000242025-09-23T04:29:29.000ZNone
6Sophia DeanTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative270943.204834198.01368.4000242025-09-23T04:29:29.000ZNone
7Sandra NunezTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative269574.804810197.01368.4000242025-09-23T04:29:29.000ZNone
8Brandon EsparzaTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative269574.804810197.01368.4000242025-09-23T04:29:29.000ZNone
9Miranda VargasTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative269574.804810197.01368.4000242025-09-23T04:29:29.000ZNone
10Eileen BaileyTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative269574.804810197.01368.4000242025-09-23T04:29:29.000ZNone
11Misty GonzalezTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative269574.804810197.01368.4000242025-09-23T04:29:29.000ZNone
12Briana McclureTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative268206.404785196.01368.4000242025-09-23T04:29:29.000ZNone
13James MillerTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative268206.404785196.01368.4000242025-09-23T04:29:29.000ZNone
14Reginald WangTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative268206.404785196.01368.4000242025-09-23T04:29:29.000ZNone
15Devin HernandezTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative266838.004761195.01368.4000242025-09-23T04:29:29.000ZNone
16Meghan ParkerTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative266838.004761195.01368.4000242025-09-23T04:29:29.000ZNone
17Lindsay HarrisTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative266838.004761195.01368.4000242025-09-23T04:29:29.000ZNone
18Jonathan SullivanTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative265469.604736194.01368.4000242025-09-23T04:29:29.000ZNone
19Stephanie SosaTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative264101.204712193.01368.4000242025-09-23T04:29:29.000ZNone
20Nicole SmithTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative264101.204712193.01368.4000242025-09-23T04:29:29.000ZNone
21Jamie AllenTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative264101.204712193.01368.4000242025-09-23T04:29:29.000ZNone
22Sharon BrownTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative262732.804688192.01368.4000242025-09-23T04:29:29.000ZNone
23Terry WelchTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative262732.804688192.01368.4000242025-09-23T04:29:29.000ZNone
24Joshua ShawTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative262732.804688192.01368.4000242025-09-23T04:29:29.000ZNone
25Clinton GreeneTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative261364.404663191.01368.4000242025-09-23T04:29:29.000ZNone
26Karen FisherTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative261364.404663191.01368.4000242025-09-23T04:29:29.000ZNone
27Angela HornTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative261364.404663191.01368.4000242025-09-23T04:29:29.000ZNone
28Tracy ChambersGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative258719.995117200.01293.5999762025-09-23T04:29:29.000ZNone
29Tonya BushGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative258719.995117200.01293.5999762025-09-23T04:29:29.000ZNone
30Lauren HatfieldGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative258719.995117200.01293.5999762025-09-23T04:29:29.000ZNone
31Cynthia HarrisTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative258627.604614189.01368.4000242025-09-23T04:29:29.000ZNone
32David TorresTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative258627.604614189.01368.4000242025-09-23T04:29:29.000ZNone
33Stacy EllisGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative257426.395142199.01293.5999762025-09-23T04:29:29.000ZNone
34Jason HillTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative257259.204590188.01368.4000242025-09-23T04:29:29.000ZNone
35James EdwardsGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative256132.795166198.01293.5999762025-09-23T04:29:29.000ZNone
36Douglas PerryGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative256132.795166198.01293.5999762025-09-23T04:29:29.000ZNone
37Amanda FullerTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative255890.804565187.01368.4000242025-09-23T04:29:29.000ZNone
38Crystal ReedTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative255890.804565187.01368.4000242025-09-23T04:29:29.000ZNone
39Amber HernandezGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative254839.195190197.01293.5999762025-09-23T04:29:29.000ZNone
40Madison HarperGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative254839.195190197.01293.5999762025-09-23T04:29:29.000ZNone
41Rebecca BradleyTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative253154.004517185.01368.4000242025-09-23T04:29:29.000ZNone
42Tiffany WaltersGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative252251.995239195.01293.5999762025-09-23T04:29:29.000ZNone
43Tracy ThomasGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative252251.995239195.01293.5999762025-09-23T04:29:29.000ZNone
44Jose MarshallGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative252251.995239195.01293.5999762025-09-23T04:29:29.000ZNone
45Robert BennettTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative251785.604492184.01368.4000242025-09-23T04:29:29.000ZNone
46Sarah ScottTXNTexas Instruments Inc.TXN Tumbles on Major Cybersecurity Breach, IP ...negative251785.604492184.01368.4000242025-09-23T04:29:29.000ZNone
47Hailey ThomasGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative250958.395264194.01293.5999762025-09-23T04:29:29.000ZNone
48George RichardGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative250958.395264194.01293.5999762025-09-23T04:29:29.000ZNone
49Ashley WaltonGMGeneral Motors Co.GM Signals Trouble as Economic Slowdown Hits A...negative250958.395264194.01293.5999762025-09-23T04:29:29.000ZNone
\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
\n", + "\n", + "\n", + "
\n", + " \n", + "\n", + "\n", + "\n", + " \n", + "
\n", + "\n", + "
\n", + " \n", + " \n", + " \n", + "
\n", + "\n", + "
\n", + "
\n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "df", + "repr_error": "Out of range float values are not JSON compliant: nan" + } + }, + "metadata": {} + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Section 2: The Skill - Creating the Custom Tool\n", + "\n", + "Now that we've validated our query, it's time to register it as a persistent **Tool**. This makes our logic available to any AI agent.\n", + "\n", + "The most important parts of this definition are the `description` fields. The main `description` tells the agent *what the tool does*, and the parameter descriptions explain *what kind of information the tool needs* to run. The LLM uses this text to decide when and how to use our tool." + ], + "metadata": { + "id": "q37akGUmrf0e" + } + }, + { + "cell_type": "code", + "source": [ + "# First, let's define the full JSON payload for our new tool.\n", + "# This includes its ID, a description for the LLM, the ES|QL query, and the parameter schema.\n", + "\n", + "tool_id = \"find_client_exposure_to_negative_news\"\n", + "\n", + "tool_definition = {\n", + " \"id\": tool_id,\n", + " \"type\": \"esql\",\n", + " \"description\": \"Finds client portfolio exposure to negative news. This tool scans recent news and reports for negative sentiment, identifies the associated asset, and finds all clients holding that asset. It returns a list sorted by the current market value of the position to highlight the highest potential risk.\",\n", + " \"configuration\": {\n", + " \"query\": \"\"\"\n", + " FROM financial_news, financial_reports METADATA _index\n", + " | WHERE sentiment == \"negative\"\n", + " | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(?time_duration)\n", + " | RENAME primary_symbol AS symbol\n", + " | LOOKUP JOIN financial_asset_details ON symbol\n", + " | LOOKUP JOIN financial_holdings ON symbol\n", + " | LOOKUP JOIN financial_accounts ON account_id\n", + " | WHERE account_holder_name IS NOT NULL\n", + " | EVAL position_current_value = quantity * current_price.price\n", + " | RENAME title AS news_title\n", + " | KEEP\n", + " account_holder_name, symbol, asset_name, news_title,\n", + " sentiment, position_current_value, quantity, current_price.price,\n", + " published_date, report_date\n", + " | SORT position_current_value DESC\n", + " | LIMIT 50\n", + " \"\"\",\n", + " \"params\": {\n", + " \"time_duration\": {\n", + " \"type\": \"keyword\",\n", + " \"description\": \"\"\"The timeframe to search back for negative news. Format is \"X hours\" DEFAULT TO 8760 hours \"\"\",\n", + " }\n", + " },\n", + " },\n", + " \"tags\": [\"retrieval\", \"risk-analysis\"],\n", + "}\n", + "\n", + "\n", + "print(f\"✅ Tool definition for '{tool_id}' is ready.\")\n", + "# Displaying the JSON we are about to send\n", + "display(JSON(tool_definition))" + ], + "metadata": { + "id": "VOateXc8roqx", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 481 + }, + "outputId": "45aaea0b-8ba5-463d-bcb0-25932c26ead1" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ Tool definition for 'find_client_exposure_to_negative_news' is ready.\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "application/json": { + "id": "find_client_exposure_to_negative_news", + "type": "esql", + "description": "Finds client portfolio exposure to negative news. This tool scans recent news and reports for negative sentiment, identifies the associated asset, and finds all clients holding that asset. It returns a list sorted by the current market value of the position to highlight the highest potential risk.", + "configuration": { + "query": "\n FROM financial_news, financial_reports METADATA _index\n | WHERE sentiment == \"negative\"\n | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(?time_duration)\n | RENAME primary_symbol AS symbol\n | LOOKUP JOIN financial_asset_details ON symbol\n | LOOKUP JOIN financial_holdings ON symbol\n | LOOKUP JOIN financial_accounts ON account_id\n | WHERE account_holder_name IS NOT NULL\n | EVAL position_current_value = quantity * current_price.price\n | RENAME title AS news_title\n | KEEP\n account_holder_name, symbol, asset_name, news_title,\n sentiment, position_current_value, quantity, current_price.price,\n published_date, report_date\n | SORT position_current_value DESC\n | LIMIT 50\n ", + "params": { + "time_duration": { + "type": "keyword", + "description": "The timeframe to search back for negative news. Format is \"X hours\" DEFAULT TO 8760 hours " + } + } + }, + "tags": [ + "retrieval", + "risk-analysis" + ] + } + }, + "metadata": { + "application/json": { + "expanded": false, + "root": "root" + } + } + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Now, let's create the tool by sending a POST request to the /api/chat/tools endpoint.\n", + "\n", + "display(Markdown(f\"Create Tool: `{tool_id}`\"))\n", + "\n", + "try:\n", + " # Note that Kibana API endpoints are prefixed with kbn:// but accessed via the standard HTTP endpoint\n", + " response = requests.post(\n", + " f\"{kb_url}/api/agent_builder/tools\", headers=HEADERS, json=tool_definition\n", + " )\n", + " response.raise_for_status()\n", + "\n", + " print(f\"✅ Successfully created the tool!\")\n", + " # Display the server's response\n", + " display(JSON(response.json()))\n", + "\n", + "except requests.exceptions.RequestException as e:\n", + " # Handle cases where the tool might already exist or other errors\n", + " if (\n", + " e.response.status_code == 400\n", + " and \"Tool with id\" in e.response.text\n", + " and \"already exists\" in e.response.text\n", + " ):\n", + " print(f\"⚠️ Tool with ID '{tool_id}' already exists. Continuing.\")\n", + " else:\n", + " print(f\"❌ Tool creation failed: {e.response.text}\")" + ], + "metadata": { + "id": "Uc-aYgXqrrrH", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 797 + }, + "outputId": "bf9aea59-fe85-4386-f152-94a7f66cbc87" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "Create Tool: `find_client_exposure_to_negative_news`" + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ Successfully created the tool!\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "application/json": { + "id": "find_client_exposure_to_negative_news", + "type": "esql", + "description": "Finds client portfolio exposure to negative news. This tool scans recent news and reports for negative sentiment, identifies the associated asset, and finds all clients holding that asset. It returns a list sorted by the current market value of the position to highlight the highest potential risk.", + "tags": [ + "retrieval", + "risk-analysis" + ], + "configuration": { + "query": "\n FROM financial_news, financial_reports METADATA _index\n | WHERE sentiment == \"negative\"\n | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(?time_duration)\n | RENAME primary_symbol AS symbol\n | LOOKUP JOIN financial_asset_details ON symbol\n | LOOKUP JOIN financial_holdings ON symbol\n | LOOKUP JOIN financial_accounts ON account_id\n | WHERE account_holder_name IS NOT NULL\n | EVAL position_current_value = quantity * current_price.price\n | RENAME title AS news_title\n | KEEP\n account_holder_name, symbol, asset_name, news_title,\n sentiment, position_current_value, quantity, current_price.price,\n published_date, report_date\n | SORT position_current_value DESC\n | LIMIT 50\n ", + "params": { + "time_duration": { + "type": "keyword", + "description": "The timeframe to search back for negative news. Format is \"X hours\" DEFAULT TO 8760 hours " + } + } + }, + "readonly": false, + "schema": { + "type": "object", + "properties": { + "time_duration": { + "type": "string", + "description": "The timeframe to search back for negative news. Format is \"X hours\" DEFAULT TO 8760 hours " + } + }, + "required": [ + "time_duration" + ], + "additionalProperties": false, + "description": "Parameters needed to execute the query", + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + }, + "metadata": { + "application/json": { + "expanded": false, + "root": "root" + } + } + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Finally, let's verify the tool was created by fetching it directly by its ID.\n", + "\n", + "display(Markdown(f\"### 🔍 Verifying Tool: `{tool_id}`\"))\n", + "\n", + "try:\n", + " response = requests.get(\n", + " f\"{kb_url}/api/agent_builder/tools/{tool_id}\", headers=HEADERS\n", + " )\n", + " response.raise_for_status()\n", + "\n", + " print(\"✅ Tool exists! Details below:\")\n", + " display(JSON(response.json()))\n", + "\n", + "except requests.exceptions.RequestException as e:\n", + " print(f\"❌ Could not retrieve tool: {e.response.text}\")" + ], + "metadata": { + "id": "KcBKZ6hjruPO", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 808 + }, + "outputId": "72802df2-b59b-4c3b-8a3f-f1b30ea086b7" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "### 🔍 Verifying Tool: `find_client_exposure_to_negative_news`" + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ Tool exists! Details below:\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "application/json": { + "id": "find_client_exposure_to_negative_news", + "type": "esql", + "description": "Finds client portfolio exposure to negative news. This tool scans recent news and reports for negative sentiment, identifies the associated asset, and finds all clients holding that asset. It returns a list sorted by the current market value of the position to highlight the highest potential risk.", + "tags": [ + "retrieval", + "risk-analysis" + ], + "configuration": { + "query": "\n FROM financial_news, financial_reports METADATA _index\n | WHERE sentiment == \"negative\"\n | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(?time_duration)\n | RENAME primary_symbol AS symbol\n | LOOKUP JOIN financial_asset_details ON symbol\n | LOOKUP JOIN financial_holdings ON symbol\n | LOOKUP JOIN financial_accounts ON account_id\n | WHERE account_holder_name IS NOT NULL\n | EVAL position_current_value = quantity * current_price.price\n | RENAME title AS news_title\n | KEEP\n account_holder_name, symbol, asset_name, news_title,\n sentiment, position_current_value, quantity, current_price.price,\n published_date, report_date\n | SORT position_current_value DESC\n | LIMIT 50\n ", + "params": { + "time_duration": { + "type": "keyword", + "description": "The timeframe to search back for negative news. Format is \"X hours\" DEFAULT TO 8760 hours " + } + } + }, + "readonly": false, + "schema": { + "type": "object", + "properties": { + "time_duration": { + "type": "string", + "description": "The timeframe to search back for negative news. Format is \"X hours\" DEFAULT TO 8760 hours " + } + }, + "required": [ + "time_duration" + ], + "additionalProperties": false, + "description": "Parameters needed to execute the query", + "$schema": "http://json-schema.org/draft-07/schema#" + } + } + }, + "metadata": { + "application/json": { + "expanded": false, + "root": "root" + } + } + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Section 3: The Brains - Creating the Custom Agent\n", + "\n", + "With our \"skill\" (the Tool) created, we now need to create the \"brain\" (the **Agent**). The Agent is the persona that combines the power of an LLM with a specific set of tools and, most importantly, a set of \"Custom Instructions.\"\n", + "\n", + "These instructions act as the agent's constitution. They define its personality, its mission, and the rules it must follow. A well-crafted prompt is the key to creating a reliable and specialized assistant." + ], + "metadata": { + "id": "n2voaqVqrx2E" + } + }, + { + "cell_type": "code", + "source": [ + "# First, let's define the detailed instructions for our \"Financial Manager\" agent.\n", + "# This prompt tells the agent who it is, what it should do, and what it absolutely should NOT do.\n", + "\n", + "financial_assistant_prompt = \"\"\"\n", + "You are a specialized Data Intelligence Assistant for financial managers, designed to provide precise, data-driven insights from information stored in Elasticsearch.\n", + "\n", + "**Your Core Mission:**\n", + "- Respond accurately and concisely to natural language queries from financial managers.\n", + "- Provide precise, objective, and actionable information derived solely from the Elasticsearch data at your disposal.\n", + "- Summarize key data points and trends based on user requests.\n", + "\n", + "**Reasoning Framework:**\n", + "1. **Understand:** Deconstruct the user's query to understand their core intent.\n", + "2. **Plan:** Formulate a step-by-step plan to answer the question. If you are unsure about the data structure, use the available tools to explore the indices first.\n", + "3. **Execute:** Use the available tools to execute your plan.\n", + "4. **Synthesize:** Combine the information from all tool calls into a single, comprehensive, and easy-to-read answer.\n", + "\n", + "**Key Directives and Constraints:**\n", + "- **If a user's request is ambiguous, ask clarifying questions before proceeding.**\n", + "- **DO NOT provide financial advice, recommendations, or predictions.** Your role is strictly informational and analytical.\n", + "- Stay strictly on topic with financial data queries.\n", + "- If you cannot answer a query, state that clearly and offer alternative ways you might help *within your data scope*.\n", + "- All numerical values should be formatted appropriately (e.g., currency, percentages).\n", + "\n", + "**Output Format:**\n", + "- All responses must be formatted using **Markdown** for clarity.\n", + "- When presenting structured data, use Markdown tables, lists, or bolding.\n", + "\n", + "**Start by greeting the financial manager and offering assistance.**\n", + "\"\"\"\n", + "\n", + "print(\"✅ Agent prompt is defined.\")" + ], + "metadata": { + "id": "zzAIKcv9r2H7", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "2d481347-cce1-40aa-efde-669349171605" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ Agent prompt is defined.\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Now, let's define the full agent payload.\n", + "# We'll give it an ID, a name, and a configuration that includes our prompt and access to our ES|QL tools.\n", + "\n", + "agent_id = \"financial_assistant\"\n", + "\n", + "agent_definition = {\n", + " \"id\": agent_id,\n", + " \"name\": \"Financial Assistant\",\n", + " \"description\": \"An assistant for analyzing and understanding your financial data\",\n", + " \"labels\": [\"Finance\"],\n", + " \"avatar_color\": \"#16C5C0\",\n", + " \"avatar_symbol\": \"💰\",\n", + " \"configuration\": {\n", + " \"instructions\": financial_assistant_prompt,\n", + " \"tools\": [\n", + " {\n", + " \"tool_ids\": [\n", + " \"platform.core.search\",\n", + " \"platform.core.list_indices\",\n", + " \"platform.core.get_index_mapping\",\n", + " \"platform.core.get_document_by_id\",\n", + " \"find_client_exposure_to_negative_news\",\n", + " ]\n", + " }\n", + " ],\n", + " },\n", + "}\n", + "\n", + "print(f\"✅ Agent definition for '{agent_id}' is ready.\")\n", + "display(JSON(agent_definition))" + ], + "metadata": { + "id": "ItkekBHcr4T5", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 660 + }, + "outputId": "ec3c564f-bffc-40bc-eb31-4f52cbc0d082" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ Agent definition for 'financial_assistant' is ready.\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "application/json": { + "id": "financial_assistant", + "name": "Financial Assistant", + "description": "An assistant for analyzing and understanding your financial data", + "labels": [ + "Finance" + ], + "avatar_color": "#16C5C0", + "avatar_symbol": "💰", + "configuration": { + "instructions": "\nYou are a specialized Data Intelligence Assistant for financial managers, designed to provide precise, data-driven insights from information stored in Elasticsearch.\n\n**Your Core Mission:**\n- Respond accurately and concisely to natural language queries from financial managers.\n- Provide precise, objective, and actionable information derived solely from the Elasticsearch data at your disposal.\n- Summarize key data points and trends based on user requests.\n\n**Reasoning Framework:**\n1. **Understand:** Deconstruct the user's query to understand their core intent.\n2. **Plan:** Formulate a step-by-step plan to answer the question. If you are unsure about the data structure, use the available tools to explore the indices first.\n3. **Execute:** Use the available tools to execute your plan.\n4. **Synthesize:** Combine the information from all tool calls into a single, comprehensive, and easy-to-read answer.\n\n**Key Directives and Constraints:**\n- **If a user's request is ambiguous, ask clarifying questions before proceeding.**\n- **DO NOT provide financial advice, recommendations, or predictions.** Your role is strictly informational and analytical.\n- Stay strictly on topic with financial data queries.\n- If you cannot answer a query, state that clearly and offer alternative ways you might help *within your data scope*.\n- All numerical values should be formatted appropriately (e.g., currency, percentages).\n\n**Output Format:**\n- All responses must be formatted using **Markdown** for clarity.\n- When presenting structured data, use Markdown tables, lists, or bolding.\n\n**Start by greeting the financial manager and offering assistance.**\n", + "tools": [ + { + "tool_ids": [ + "platform.core.search", + "platform.core.list_indices", + "platform.core.get_index_mapping", + "platform.core.get_document_by_id", + "find_client_exposure_to_negative_news" + ] + } + ] + } + } + }, + "metadata": { + "application/json": { + "expanded": false, + "root": "root" + } + } + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Create the agent by sending a POST request to the /api/chat/agents endpoint.\n", + "\n", + "display(Markdown(f\"### 🤖 Creating Agent: `{agent_id}`\"))\n", + "\n", + "try:\n", + " response = requests.post(\n", + " f\"{kb_url}/api/agent_builder/agents\", headers=HEADERS, json=agent_definition\n", + " )\n", + " response.raise_for_status()\n", + "\n", + " print(f\"✅ Successfully created the agent!\")\n", + " display(JSON(response.json()))\n", + "\n", + "except requests.exceptions.RequestException as e:\n", + " if e.response.status_code == 409:\n", + " print(f\"⚠️ Agent with ID '{agent_id}' already exists. Continuing.\")\n", + " else:\n", + " print(f\"❌ Agent creation failed: {e.response.text}\")" + ], + "metadata": { + "id": "lvIESp2Ir7qC", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 718 + }, + "outputId": "85f86437-0ad3-4d12-cb65-9083c3458217" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "### 🤖 Creating Agent: `financial_assistant`" + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ Successfully created the agent!\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "application/json": { + "id": "financial_assistant", + "type": "chat", + "name": "Financial Assistant", + "description": "An assistant for analyzing and understanding your financial data", + "labels": [ + "Finance" + ], + "avatar_color": "#16C5C0", + "avatar_symbol": "💰", + "configuration": { + "instructions": "\nYou are a specialized Data Intelligence Assistant for financial managers, designed to provide precise, data-driven insights from information stored in Elasticsearch.\n\n**Your Core Mission:**\n- Respond accurately and concisely to natural language queries from financial managers.\n- Provide precise, objective, and actionable information derived solely from the Elasticsearch data at your disposal.\n- Summarize key data points and trends based on user requests.\n\n**Reasoning Framework:**\n1. **Understand:** Deconstruct the user's query to understand their core intent.\n2. **Plan:** Formulate a step-by-step plan to answer the question. If you are unsure about the data structure, use the available tools to explore the indices first.\n3. **Execute:** Use the available tools to execute your plan.\n4. **Synthesize:** Combine the information from all tool calls into a single, comprehensive, and easy-to-read answer.\n\n**Key Directives and Constraints:**\n- **If a user's request is ambiguous, ask clarifying questions before proceeding.**\n- **DO NOT provide financial advice, recommendations, or predictions.** Your role is strictly informational and analytical.\n- Stay strictly on topic with financial data queries.\n- If you cannot answer a query, state that clearly and offer alternative ways you might help *within your data scope*.\n- All numerical values should be formatted appropriately (e.g., currency, percentages).\n\n**Output Format:**\n- All responses must be formatted using **Markdown** for clarity.\n- When presenting structured data, use Markdown tables, lists, or bolding.\n\n**Start by greeting the financial manager and offering assistance.**\n", + "tools": [ + { + "tool_ids": [ + "platform.core.search", + "platform.core.list_indices", + "platform.core.get_index_mapping", + "platform.core.get_document_by_id", + "find_client_exposure_to_negative_news" + ] + } + ] + } + } + }, + "metadata": { + "application/json": { + "expanded": false, + "root": "root" + } + } + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Finally, let's verify the agent was created by fetching it directly by its ID.\n", + "\n", + "display(Markdown(f\"### 🔍 Verifying Agent: `{agent_id}`\"))\n", + "\n", + "try:\n", + " response = requests.get(\n", + " f\"{kb_url}/api/agent_builder/agents/{agent_id}\", headers=HEADERS\n", + " )\n", + " response.raise_for_status()\n", + "\n", + " print(\"✅ Agent exists! Details below:\")\n", + " display(JSON(response.json()))\n", + "\n", + "except requests.exceptions.RequestException as e:\n", + " print(f\"❌ Could not retrieve agent: {e.response.text}\")" + ], + "metadata": { + "id": "bbggcUOIr8NT", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 718 + }, + "outputId": "d56e7519-575e-429d-ddd4-7806ca5f6dcd" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "### 🔍 Verifying Agent: `financial_assistant`" + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ Agent exists! Details below:\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "application/json": { + "id": "financial_assistant", + "type": "chat", + "name": "Financial Assistant", + "description": "An assistant for analyzing and understanding your financial data", + "labels": [ + "Finance" + ], + "avatar_color": "#16C5C0", + "avatar_symbol": "💰", + "configuration": { + "instructions": "\nYou are a specialized Data Intelligence Assistant for financial managers, designed to provide precise, data-driven insights from information stored in Elasticsearch.\n\n**Your Core Mission:**\n- Respond accurately and concisely to natural language queries from financial managers.\n- Provide precise, objective, and actionable information derived solely from the Elasticsearch data at your disposal.\n- Summarize key data points and trends based on user requests.\n\n**Reasoning Framework:**\n1. **Understand:** Deconstruct the user's query to understand their core intent.\n2. **Plan:** Formulate a step-by-step plan to answer the question. If you are unsure about the data structure, use the available tools to explore the indices first.\n3. **Execute:** Use the available tools to execute your plan.\n4. **Synthesize:** Combine the information from all tool calls into a single, comprehensive, and easy-to-read answer.\n\n**Key Directives and Constraints:**\n- **If a user's request is ambiguous, ask clarifying questions before proceeding.**\n- **DO NOT provide financial advice, recommendations, or predictions.** Your role is strictly informational and analytical.\n- Stay strictly on topic with financial data queries.\n- If you cannot answer a query, state that clearly and offer alternative ways you might help *within your data scope*.\n- All numerical values should be formatted appropriately (e.g., currency, percentages).\n\n**Output Format:**\n- All responses must be formatted using **Markdown** for clarity.\n- When presenting structured data, use Markdown tables, lists, or bolding.\n\n**Start by greeting the financial manager and offering assistance.**\n", + "tools": [ + { + "tool_ids": [ + "platform.core.search", + "platform.core.list_indices", + "platform.core.get_index_mapping", + "platform.core.get_document_by_id", + "find_client_exposure_to_negative_news" + ] + } + ] + } + } + }, + "metadata": { + "application/json": { + "expanded": false, + "root": "root" + } + } + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Section 4: The Payoff! — Chatting with the Agent\n", + "\n", + "Everything is now in place. We have our logic (the Tool) and our expert persona (the Agent). It's time to ask our `Financial Assistant` agent the complex, multi-step question from the blog post and see how it performs.\n", + "\n", + "We'll send our question to the `/api/agent_builder/converse` endpoint, making sure to specify our agent's ID." + ], + "metadata": { + "id": "Pp90C3DWr_ap" + } + }, + { + "cell_type": "code", + "source": [ + "# First, define the complex question we want to ask.\n", + "# user_question = \"Who has the highest account value and what is their highest valued individual asset?\"\n", + "user_question = \"I'm worried about market sentiment. Can you show me which of our clients are most at risk from bad news?\"\n", + "\n", + "# Next, construct the request body for the /api/agent_builder/converse endpoint.\n", + "# It's crucial that we specify the `agent_id` so we talk to our custom agent.\n", + "chat_request_body = {\n", + " \"input\": user_question,\n", + " \"agent_id\": agent_id, # Using the agent_id variable from the previous section\n", + "}\n", + "\n", + "\n", + "print(f\"✅ Chat request for agent '{agent_id}' is ready.\")\n", + "display(JSON(chat_request_body))" + ], + "metadata": { + "id": "nQ221TR1sDzJ", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 106 + }, + "outputId": "fd8a8324-1f32-43d9-8949-04268b770770" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ Chat request for agent 'financial_assistant' is ready.\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "application/json": { + "input": "I'm worried about market sentiment. Can you show me which of our clients are most at risk from bad news?", + "agent_id": "financial_assistant" + } + }, + "metadata": { + "application/json": { + "expanded": false, + "root": "root" + } + } + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Now, let's send the request and start the conversation!\n", + "# This single API call will trigger the agent's complex reasoning process.\n", + "\n", + "display(Markdown(f\"### 💬 Asking: '{user_question}'\"))\n", + "\n", + "chat_response = None # Initialize variable to store the response\n", + "\n", + "try:\n", + " response = requests.post(\n", + " f\"{kb_url}/api/agent_builder/converse\", headers=HEADERS, json=chat_request_body\n", + " )\n", + " response.raise_for_status()\n", + "\n", + " chat_response = response.json()\n", + " print(\"✅ Agent responded successfully! See the analysis in the next cell.\")\n", + "\n", + "except requests.exceptions.RequestException as e:\n", + " print(f\"❌ Chat request failed: {e.response.text}\")" + ], + "metadata": { + "id": "6Hvr9JSfsLsi", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 76 + }, + "outputId": "6647c5ba-001b-4fe8-a197-88db08410fc1" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "### 💬 Asking: 'I'm worried about market sentiment. Can you show me which of our clients are most at risk from bad news?'" + }, + "metadata": {} + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "✅ Agent responded successfully! See the analysis in the next cell.\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Analyzing the Response\n", + "\n", + "The agent's response contains three key parts:\n", + "1. **The Conversation ID:** A unique ID to continue this specific chat thread.\n", + "2. **The Final Message:** The human-readable answer, formatted in Markdown as we requested in our prompt.\n", + "3. **The Steps:** A detailed log of the agent's \"thought process,\" showing every tool it called and the parameters it used to arrive at the answer." + ], + "metadata": { + "id": "CLAY9ZNSsPLN" + } + }, + { + "cell_type": "code", + "source": [ + "chat_response[\"steps\"]" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "QwtC5PcUEynT", + "outputId": "ea51f9de-668f-491d-d6f2-fb6693324e85" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[{'type': 'reasoning',\n", + " 'reasoning': 'The user is concerned about market sentiment and wants to identify clients most at risk from negative news. The find_client_exposure_to_negative_news tool is specifically designed for this purpose, as it scans recent news for negative sentiment, identifies affected assets, and finds clients holding those assets.'},\n", + " {'type': 'tool_call',\n", + " 'tool_call_id': 'tooluse_ME2S2H88Qp-GXYBw3WaxNg',\n", + " 'tool_id': 'find_client_exposure_to_negative_news',\n", + " 'progression': [],\n", + " 'params': {'time_duration': '24 hours'},\n", + " 'results': [{'type': 'query',\n", + " 'data': {'esql': '\\n FROM financial_news, financial_reports METADATA _index\\n | WHERE sentiment == \"negative\"\\n | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(\"24 hours\")\\n | RENAME primary_symbol AS symbol\\n | LOOKUP JOIN financial_asset_details ON symbol\\n | LOOKUP JOIN financial_holdings ON symbol\\n | LOOKUP JOIN financial_accounts ON account_id\\n | WHERE account_holder_name IS NOT NULL\\n | EVAL position_current_value = quantity * current_price.price\\n | RENAME title AS news_title\\n | KEEP\\n account_holder_name, symbol, asset_name, news_title,\\n sentiment, position_current_value, quantity, current_price.price,\\n published_date, report_date\\n | SORT position_current_value DESC\\n | LIMIT 50\\n '}},\n", + " {'tool_result_id': 'zMEm',\n", + " 'type': 'tabular_data',\n", + " 'data': {'source': 'esql',\n", + " 'query': '\\n FROM financial_news, financial_reports METADATA _index\\n | WHERE sentiment == \"negative\"\\n | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(\"24 hours\")\\n | RENAME primary_symbol AS symbol\\n | LOOKUP JOIN financial_asset_details ON symbol\\n | LOOKUP JOIN financial_holdings ON symbol\\n | LOOKUP JOIN financial_accounts ON account_id\\n | WHERE account_holder_name IS NOT NULL\\n | EVAL position_current_value = quantity * current_price.price\\n | RENAME title AS news_title\\n | KEEP\\n account_holder_name, symbol, asset_name, news_title,\\n sentiment, position_current_value, quantity, current_price.price,\\n published_date, report_date\\n | SORT position_current_value DESC\\n | LIMIT 50\\n ',\n", + " 'columns': [{'name': 'account_holder_name', 'type': 'text'},\n", + " {'name': 'symbol', 'type': 'keyword'},\n", + " {'name': 'asset_name', 'type': 'text'},\n", + " {'name': 'news_title', 'type': 'text'},\n", + " {'name': 'sentiment', 'type': 'keyword'},\n", + " {'name': 'position_current_value', 'type': 'double'},\n", + " {'name': 'quantity', 'type': 'double'},\n", + " {'name': 'current_price.price', 'type': 'double'},\n", + " {'name': 'published_date', 'type': 'date'},\n", + " {'name': 'report_date', 'type': 'date'}],\n", + " 'values': [['Victoria Schneider',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 273680.0048828125,\n", + " 200,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Jillian Davis',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 272311.60485839844,\n", + " 199,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Lorraine Gibson',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 272311.60485839844,\n", + " 199,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Craig Griffith',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 272311.60485839844,\n", + " 199,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Jeffrey Byrd',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 270943.2048339844,\n", + " 198,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Patrick Rice',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 270943.2048339844,\n", + " 198,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Sophia Dean',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 270943.2048339844,\n", + " 198,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Eileen Bailey',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 269574.8048095703,\n", + " 197,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Sandra Nunez',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 269574.8048095703,\n", + " 197,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Brandon Esparza',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 269574.8048095703,\n", + " 197,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Miranda Vargas',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 269574.8048095703,\n", + " 197,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Misty Gonzalez',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 269574.8048095703,\n", + " 197,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Reginald Wang',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 268206.40478515625,\n", + " 196,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Briana Mcclure',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 268206.40478515625,\n", + " 196,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['James Miller',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 268206.40478515625,\n", + " 196,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Meghan Parker',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 266838.0047607422,\n", + " 195,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Lindsay Harris',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 266838.0047607422,\n", + " 195,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Devin Hernandez',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 266838.0047607422,\n", + " 195,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Jonathan Sullivan',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 265469.6047363281,\n", + " 194,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Nicole Smith',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 264101.20471191406,\n", + " 193,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Stephanie Sosa',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 264101.20471191406,\n", + " 193,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Jamie Allen',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 264101.20471191406,\n", + " 193,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Sharon Brown',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 262732.8046875,\n", + " 192,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Joshua Shaw',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 262732.8046875,\n", + " 192,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Terry Welch',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 262732.8046875,\n", + " 192,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Clinton Greene',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 261364.40466308594,\n", + " 191,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Karen Fisher',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 261364.40466308594,\n", + " 191,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Angela Horn',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 261364.40466308594,\n", + " 191,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Lauren Hatfield',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 258719.9951171875,\n", + " 200,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Tracy Chambers',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 258719.9951171875,\n", + " 200,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Tonya Bush',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 258719.9951171875,\n", + " 200,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Cynthia Harris',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 258627.6046142578,\n", + " 189,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['David Torres',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 258627.6046142578,\n", + " 189,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Stacy Ellis',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 257426.39514160156,\n", + " 199,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Jason Hill',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 257259.20458984375,\n", + " 188,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Douglas Perry',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 256132.79516601562,\n", + " 198,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['James Edwards',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 256132.79516601562,\n", + " 198,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Crystal Reed',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 255890.8045654297,\n", + " 187,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Amanda Fuller',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 255890.8045654297,\n", + " 187,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Amber Hernandez',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 254839.1951904297,\n", + " 197,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Madison Harper',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 254839.1951904297,\n", + " 197,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Rebecca Bradley',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 253154.00451660156,\n", + " 185,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Jose Marshall',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 252251.9952392578,\n", + " 195,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Tiffany Walters',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 252251.9952392578,\n", + " 195,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Tracy Thomas',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 252251.9952392578,\n", + " 195,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Robert Bennett',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 251785.6044921875,\n", + " 184,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Sarah Scott',\n", + " 'TXN',\n", + " 'Texas Instruments Inc.',\n", + " 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk',\n", + " 'negative',\n", + " 251785.6044921875,\n", + " 184,\n", + " 1368.4000244140625,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Ashley Walton',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 250958.39526367188,\n", + " 194,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['Hailey Thomas',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 250958.39526367188,\n", + " 194,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None],\n", + " ['George Richard',\n", + " 'GM',\n", + " 'General Motors Co.',\n", + " 'GM Signals Trouble as Economic Slowdown Hits Auto Demand',\n", + " 'negative',\n", + " 250958.39526367188,\n", + " 194,\n", + " 1293.5999755859375,\n", + " '2025-09-23T04:29:29.000Z',\n", + " None]]}}]}]" + ] + }, + "metadata": {}, + "execution_count": 42 + } + ] + }, + { + "cell_type": "code", + "source": [ + "chat_response.keys()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "JdQlHM3eE_OE", + "outputId": "11cf15f0-6c42-4965-cb0d-265634c7b50e" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "dict_keys(['conversation_id', 'steps', 'response'])" + ] + }, + "metadata": {}, + "execution_count": 37 + } + ] + }, + { + "cell_type": "code", + "source": [ + "steps = chat_response.get(\"steps\", [])\n", + "for i, step in enumerate(steps):\n", + " print(step)\n", + " tool_id = step.get(\"tool_id\")\n", + " tool_params = step.get(\"params\", {})\n", + " display(Markdown(f\"**Step {i+1}: Call Tool `{tool_id}`**\"))\n", + " display(JSON(tool_params))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 204 + }, + "id": "_R9VYFeQFKe5", + "outputId": "1fff3b45-2bdf-40a9-f15c-9474086beac3" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "{'type': 'reasoning', 'reasoning': 'The user is concerned about market sentiment and wants to identify clients most at risk from negative news. The find_client_exposure_to_negative_news tool is specifically designed for this purpose, as it scans recent news for negative sentiment, identifies affected assets, and finds clients holding those assets.'}\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "**Step 1: Call Tool `None`**" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "application/json": {} + }, + "metadata": { + "application/json": { + "expanded": false, + "root": "root" + } + } + }, + { + "output_type": "stream", + "name": "stdout", + "text": [ + "{'type': 'tool_call', 'tool_call_id': 'tooluse_ME2S2H88Qp-GXYBw3WaxNg', 'tool_id': 'find_client_exposure_to_negative_news', 'progression': [], 'params': {'time_duration': '24 hours'}, 'results': [{'type': 'query', 'data': {'esql': '\\n FROM financial_news, financial_reports METADATA _index\\n | WHERE sentiment == \"negative\"\\n | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(\"24 hours\")\\n | RENAME primary_symbol AS symbol\\n | LOOKUP JOIN financial_asset_details ON symbol\\n | LOOKUP JOIN financial_holdings ON symbol\\n | LOOKUP JOIN financial_accounts ON account_id\\n | WHERE account_holder_name IS NOT NULL\\n | EVAL position_current_value = quantity * current_price.price\\n | RENAME title AS news_title\\n | KEEP\\n account_holder_name, symbol, asset_name, news_title,\\n sentiment, position_current_value, quantity, current_price.price,\\n published_date, report_date\\n | SORT position_current_value DESC\\n | LIMIT 50\\n '}}, {'tool_result_id': 'zMEm', 'type': 'tabular_data', 'data': {'source': 'esql', 'query': '\\n FROM financial_news, financial_reports METADATA _index\\n | WHERE sentiment == \"negative\"\\n | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(\"24 hours\")\\n | RENAME primary_symbol AS symbol\\n | LOOKUP JOIN financial_asset_details ON symbol\\n | LOOKUP JOIN financial_holdings ON symbol\\n | LOOKUP JOIN financial_accounts ON account_id\\n | WHERE account_holder_name IS NOT NULL\\n | EVAL position_current_value = quantity * current_price.price\\n | RENAME title AS news_title\\n | KEEP\\n account_holder_name, symbol, asset_name, news_title,\\n sentiment, position_current_value, quantity, current_price.price,\\n published_date, report_date\\n | SORT position_current_value DESC\\n | LIMIT 50\\n ', 'columns': [{'name': 'account_holder_name', 'type': 'text'}, {'name': 'symbol', 'type': 'keyword'}, {'name': 'asset_name', 'type': 'text'}, {'name': 'news_title', 'type': 'text'}, {'name': 'sentiment', 'type': 'keyword'}, {'name': 'position_current_value', 'type': 'double'}, {'name': 'quantity', 'type': 'double'}, {'name': 'current_price.price', 'type': 'double'}, {'name': 'published_date', 'type': 'date'}, {'name': 'report_date', 'type': 'date'}], 'values': [['Victoria Schneider', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 273680.0048828125, 200, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Jillian Davis', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 272311.60485839844, 199, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Lorraine Gibson', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 272311.60485839844, 199, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Craig Griffith', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 272311.60485839844, 199, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Jeffrey Byrd', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 270943.2048339844, 198, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Patrick Rice', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 270943.2048339844, 198, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Sophia Dean', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 270943.2048339844, 198, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Eileen Bailey', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 269574.8048095703, 197, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Sandra Nunez', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 269574.8048095703, 197, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Brandon Esparza', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 269574.8048095703, 197, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Miranda Vargas', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 269574.8048095703, 197, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Misty Gonzalez', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 269574.8048095703, 197, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Reginald Wang', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 268206.40478515625, 196, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Briana Mcclure', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 268206.40478515625, 196, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['James Miller', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 268206.40478515625, 196, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Meghan Parker', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 266838.0047607422, 195, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Lindsay Harris', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 266838.0047607422, 195, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Devin Hernandez', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 266838.0047607422, 195, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Jonathan Sullivan', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 265469.6047363281, 194, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Nicole Smith', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 264101.20471191406, 193, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Stephanie Sosa', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 264101.20471191406, 193, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Jamie Allen', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 264101.20471191406, 193, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Sharon Brown', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 262732.8046875, 192, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Joshua Shaw', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 262732.8046875, 192, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Terry Welch', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 262732.8046875, 192, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Clinton Greene', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 261364.40466308594, 191, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Karen Fisher', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 261364.40466308594, 191, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Angela Horn', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 261364.40466308594, 191, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Lauren Hatfield', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 258719.9951171875, 200, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['Tracy Chambers', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 258719.9951171875, 200, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['Tonya Bush', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 258719.9951171875, 200, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['Cynthia Harris', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 258627.6046142578, 189, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['David Torres', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 258627.6046142578, 189, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Stacy Ellis', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 257426.39514160156, 199, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['Jason Hill', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 257259.20458984375, 188, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Douglas Perry', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 256132.79516601562, 198, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['James Edwards', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 256132.79516601562, 198, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['Crystal Reed', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 255890.8045654297, 187, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Amanda Fuller', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 255890.8045654297, 187, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Amber Hernandez', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 254839.1951904297, 197, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['Madison Harper', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 254839.1951904297, 197, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['Rebecca Bradley', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 253154.00451660156, 185, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Jose Marshall', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 252251.9952392578, 195, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['Tiffany Walters', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 252251.9952392578, 195, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['Tracy Thomas', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 252251.9952392578, 195, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['Robert Bennett', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 251785.6044921875, 184, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Sarah Scott', 'TXN', 'Texas Instruments Inc.', 'TXN Tumbles on Major Cybersecurity Breach, IP at Risk', 'negative', 251785.6044921875, 184, 1368.4000244140625, '2025-09-23T04:29:29.000Z', None], ['Ashley Walton', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 250958.39526367188, 194, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['Hailey Thomas', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 250958.39526367188, 194, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None], ['George Richard', 'GM', 'General Motors Co.', 'GM Signals Trouble as Economic Slowdown Hits Auto Demand', 'negative', 250958.39526367188, 194, 1293.5999755859375, '2025-09-23T04:29:29.000Z', None]]}}]}\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "**Step 2: Call Tool `find_client_exposure_to_negative_news`**" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "application/json": { + "time_duration": "24 hours" + } + }, + "metadata": { + "application/json": { + "expanded": false, + "root": "root" + } + } + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Let's parse the response from the previous cell and display each part clearly.\n", + "\n", + "if chat_response:\n", + " # 1. Print the Conversation ID\n", + " conversation_id = chat_response.get(\"conversation_id\")\n", + " display(Markdown(f\"### Conversation ID\\n`{conversation_id}`\"))\n", + "\n", + " # 2. Display the final, formatted message\n", + " final_message = chat_response.get(\"response\", {}).get(\n", + " \"message\", \"No message found.\"\n", + " )\n", + " display(Markdown(\"---\"))\n", + " display(Markdown(f\"### Final Answer\\n{final_message}\"))\n", + " display(Markdown(\"---\"))\n", + "\n", + " # 3. Show the agent's step-by-step reasoning\n", + " steps = chat_response.get(\"steps\", [])\n", + " display(Markdown(f\"### Agent's Reasoning: {len(steps)} Steps\"))\n", + "\n", + " for i, step in enumerate(steps):\n", + " if step.get(\"type\") == \"reasoning\":\n", + " display(Markdown(f\"**Step {i+1}: Call Tool is Reasoning**\"))\n", + " display(step.get(\"reasoning\"))\n", + " elif step.get(\"type\") == \"tool_call\":\n", + " tool_id = step.get(\"tool_id\")\n", + " tool_params = step.get(\"params\", {})\n", + " display(Markdown(f\"**Step {i+1}: Call Tool `{tool_id}`**\"))\n", + " display(JSON(tool_params))\n", + "\n", + "else:\n", + " print(\n", + " \"⚠️ Chat response variable is empty. Please run the previous cell successfully.\"\n", + " )" + ], + "metadata": { + "id": "gDTpr2JksNPf", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + }, + "outputId": "0182504b-6199-4180-84e1-6bb4c5b29f76" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "### Conversation ID\n`5a6e7969-6a67-43cb-a3c7-fc12c83ff122`" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "---" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "### Final Answer\n# Client Exposure to Negative News - Last 24 Hours\n\n## Key Findings\n\nI've analyzed the market for negative news in the past 24 hours and identified two major issues affecting our clients:\n\n1. **Texas Instruments (TXN)** - Major cybersecurity breach with intellectual property at risk\n2. **General Motors (GM)** - Economic slowdown impacting auto demand\n\n## Clients with Highest Exposure\n\n### Texas Instruments (TXN) - Current Price: $1,368.40\n\n| Client Name | Position Value ($) | Shares |\n|-------------|------------------:|-------:|\n| Victoria Schneider | 273,680.00 | 200 |\n| Jillian Davis | 272,311.60 | 199 |\n| Lorraine Gibson | 272,311.60 | 199 |\n| Craig Griffith | 272,311.60 | 199 |\n| Jeffrey Byrd | 270,943.20 | 198 |\n\n### General Motors (GM) - Current Price: $1,293.60\n\n| Client Name | Position Value ($) | Shares |\n|-------------|------------------:|-------:|\n| Lauren Hatfield | 258,720.00 | 200 |\n| Tracy Chambers | 258,720.00 | 200 |\n| Tonya Bush | 258,720.00 | 200 |\n| Stacy Ellis | 257,426.40 | 199 |\n| Douglas Perry | 256,132.80 | 198 |\n\n## Summary\n\nA total of 50 clients have significant exposure to these negative news events. The most affected clients hold positions valued between $250,000 and $274,000. The Texas Instruments cybersecurity breach appears to be affecting more clients with higher position values than the General Motors economic slowdown news.\n\n" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "---" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "### Agent's Reasoning: 2 Steps" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "**Step 1: Call Tool is Reasoning**" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "'The user is concerned about market sentiment and wants to identify clients most at risk from negative news. The find_client_exposure_to_negative_news tool is specifically designed for this purpose, as it scans recent news for negative sentiment, identifies affected assets, and finds clients holding those assets.'" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "string" + } + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "**Step 2: Call Tool `find_client_exposure_to_negative_news`**" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "application/json": { + "time_duration": "24 hours" + } + }, + "metadata": { + "application/json": { + "expanded": false, + "root": "root" + } + } + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Section 5: Next Steps\n", + "\n", + "You've successfully built and chatted with a custom AI agent! This final section covers:\n", + "1. **Continuing a Conversation:** How to ask follow-up questions while maintaining the chat's context.\n", + "2. **History**: How to retrieve conversation history\n" + ], + "metadata": { + "id": "7vpozNy6salb" + } + }, + { + "cell_type": "markdown", + "source": [ + "### Continuing a Conversation\n", + "The `conversation_id` returned from our first chat request is the key to memory. By including it in subsequent requests, you tell the agent to consider the previous turns of the conversation for context." + ], + "metadata": { + "id": "17w7-YLmsfbp" + } + }, + { + "cell_type": "code", + "source": [ + "# Let's ask a follow-up question using the conversation_id from the previous section.\n", + "\n", + "if \"conversation_id\" in locals() and conversation_id:\n", + " follow_up_question = \"Summarize the first article mentioned.\"\n", + "\n", + " follow_up_body = {\n", + " \"input\": follow_up_question,\n", + " \"conversation_id\": conversation_id,\n", + " # No agent_id is needed, as it's tied to the conversation\n", + " }\n", + "\n", + " display(Markdown(f\"### 💬 Asking Follow-up: '{follow_up_question}'\"))\n", + "\n", + " try:\n", + " response = requests.post(\n", + " f\"{kb_url}/api/agent_builder/converse\", headers=HEADERS, json=follow_up_body\n", + " )\n", + " response.raise_for_status()\n", + "\n", + " follow_up_response = response.json()\n", + " final_message = follow_up_response.get(\"response\", {}).get(\n", + " \"message\", \"No message found.\"\n", + " )\n", + "\n", + " # MODIFICATION: Wrap the final message in a code block for clean formatting\n", + " display(Markdown(f\"### Follow-up Answer\\n\\n```text\\n{final_message}\\n```\"))\n", + "\n", + " except requests.exceptions.RequestException as e:\n", + " print(f\"❌ Chat request failed: {e.response.text}\")\n", + "else:\n", + " print(\"⚠️ `conversation_id` not found. Please run Section 4 successfully first.\")" + ], + "metadata": { + "id": "XNwJiz6DsdF1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 548 + }, + "outputId": "6d280892-f0b7-4923-d580-3057bc907993" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "### 💬 Asking Follow-up: 'Summarize the first article mentioned.'" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "### Follow-up Answer\n\n```text\n# Summary: TXN Tumbles on Major Cybersecurity Breach, IP at Risk\n\nTexas Instruments (TXN) has confirmed a significant cybersecurity breach where unauthorized actors gained access to the company's internal servers. According to the article published on September 23, 2025:\n\n## Key Points:\n\n- Unauthorized actors accessed Texas Instruments' internal servers\n- Early reports suggest sensitive intellectual property was compromised, including:\n - Proprietary chip designs\n - Customer data\n\n- The full extent of the breach is still under investigation\n- Texas Instruments has:\n - Engaged leading cybersecurity firms\n - Started cooperating with federal authorities\n\n## Market Impact:\n\n- TXN stock tumbled in pre-market trading\n- Investors are concerned about:\n - Potential reputational damage\n - Competitive disadvantage from stolen intellectual property\n - Costly remediation efforts\n\nThe incident has raised serious concerns about security vulnerabilities in critical supply chains within the technology sector.\n```" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Retrieving Conversation History\n", + "You can also retrieve the full history of any conversation using its ID." + ], + "metadata": { + "id": "CIk8Wa-Esj5k" + } + }, + { + "cell_type": "code", + "source": [ + "# Fetch the full history for our conversation\n", + "\n", + "if \"conversation_id\" in locals() and conversation_id:\n", + " display(\n", + " Markdown(\n", + " f\"### 📖 Retrieving Full History for Conversation:\\n`{conversation_id}`\"\n", + " )\n", + " )\n", + " try:\n", + " response = requests.get(\n", + " f\"{kb_url}/api/agent_builder/conversations/{conversation_id}\",\n", + " headers=HEADERS,\n", + " )\n", + " response.raise_for_status()\n", + "\n", + " display(JSON(response.json()))\n", + "\n", + " except requests.exceptions.RequestException as e:\n", + " print(f\"❌ Could not retrieve conversation: {e.response.text}\")\n", + "else:\n", + " print(\"⚠️ `conversation_id` not found. Please run Section 4 successfully first.\")" + ], + "metadata": { + "id": "s-D1DYUJsiM3", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + }, + "outputId": "9ea7112c-5ddb-4011-e770-8062500160ea" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "text/markdown": "### 📖 Retrieving Full History for Conversation:\n`5a6e7969-6a67-43cb-a3c7-fc12c83ff122`" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "" + ], + "application/json": { + "id": "5a6e7969-6a67-43cb-a3c7-fc12c83ff122", + "agent_id": "financial_assistant", + "user": { + "username": "3953873479" + }, + "title": "Client Risk Assessment Due to Market Sentiment", + "created_at": "2025-09-23T05:32:04.689Z", + "updated_at": "2025-09-23T05:32:04.689Z", + "rounds": [ + { + "id": "1e5d28f4-9809-4978-b04c-b070a7f5c70a", + "input": { + "message": "I'm worried about market sentiment. Can you show me which of our clients are most at risk from bad news?" + }, + "steps": [ + { + "type": "reasoning", + "reasoning": "The user is concerned about market sentiment and wants to identify clients most at risk from negative news. The find_client_exposure_to_negative_news tool is specifically designed for this purpose, as it scans recent news for negative sentiment, identifies affected assets, and finds clients holding those assets." + }, + { + "type": "tool_call", + "tool_call_id": "tooluse_ME2S2H88Qp-GXYBw3WaxNg", + "tool_id": "find_client_exposure_to_negative_news", + "progression": [], + "params": { + "time_duration": "24 hours" + }, + "results": [ + { + "type": "query", + "data": { + "esql": "\n FROM financial_news, financial_reports METADATA _index\n | WHERE sentiment == \"negative\"\n | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(\"24 hours\")\n | RENAME primary_symbol AS symbol\n | LOOKUP JOIN financial_asset_details ON symbol\n | LOOKUP JOIN financial_holdings ON symbol\n | LOOKUP JOIN financial_accounts ON account_id\n | WHERE account_holder_name IS NOT NULL\n | EVAL position_current_value = quantity * current_price.price\n | RENAME title AS news_title\n | KEEP\n account_holder_name, symbol, asset_name, news_title,\n sentiment, position_current_value, quantity, current_price.price,\n published_date, report_date\n | SORT position_current_value DESC\n | LIMIT 50\n " + } + }, + { + "tool_result_id": "zMEm", + "type": "tabular_data", + "data": { + "source": "esql", + "query": "\n FROM financial_news, financial_reports METADATA _index\n | WHERE sentiment == \"negative\"\n | WHERE coalesce(published_date, report_date) >= NOW() - TO_TIMEDURATION(\"24 hours\")\n | RENAME primary_symbol AS symbol\n | LOOKUP JOIN financial_asset_details ON symbol\n | LOOKUP JOIN financial_holdings ON symbol\n | LOOKUP JOIN financial_accounts ON account_id\n | WHERE account_holder_name IS NOT NULL\n | EVAL position_current_value = quantity * current_price.price\n | RENAME title AS news_title\n | KEEP\n account_holder_name, symbol, asset_name, news_title,\n sentiment, position_current_value, quantity, current_price.price,\n published_date, report_date\n | SORT position_current_value DESC\n | LIMIT 50\n ", + "columns": [ + { + "name": "account_holder_name", + "type": "text" + }, + { + "name": "symbol", + "type": "keyword" + }, + { + "name": "asset_name", + "type": "text" + }, + { + "name": "news_title", + "type": "text" + }, + { + "name": "sentiment", + "type": "keyword" + }, + { + "name": "position_current_value", + "type": "double" + }, + { + "name": "quantity", + "type": "double" + }, + { + "name": "current_price.price", + "type": "double" + }, + { + "name": "published_date", + "type": "date" + }, + { + "name": "report_date", + "type": "date" + } + ], + "values": [ + [ + "Victoria Schneider", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 273680.0048828125, + 200, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Jillian Davis", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 272311.60485839844, + 199, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Lorraine Gibson", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 272311.60485839844, + 199, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Craig Griffith", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 272311.60485839844, + 199, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Jeffrey Byrd", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 270943.2048339844, + 198, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Patrick Rice", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 270943.2048339844, + 198, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Sophia Dean", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 270943.2048339844, + 198, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Eileen Bailey", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 269574.8048095703, + 197, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Sandra Nunez", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 269574.8048095703, + 197, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Brandon Esparza", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 269574.8048095703, + 197, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Miranda Vargas", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 269574.8048095703, + 197, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Misty Gonzalez", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 269574.8048095703, + 197, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Reginald Wang", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 268206.40478515625, + 196, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Briana Mcclure", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 268206.40478515625, + 196, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "James Miller", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 268206.40478515625, + 196, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Meghan Parker", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 266838.0047607422, + 195, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Lindsay Harris", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 266838.0047607422, + 195, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Devin Hernandez", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 266838.0047607422, + 195, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Jonathan Sullivan", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 265469.6047363281, + 194, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Nicole Smith", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 264101.20471191406, + 193, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Stephanie Sosa", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 264101.20471191406, + 193, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Jamie Allen", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 264101.20471191406, + 193, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Sharon Brown", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 262732.8046875, + 192, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Joshua Shaw", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 262732.8046875, + 192, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Terry Welch", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 262732.8046875, + 192, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Clinton Greene", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 261364.40466308594, + 191, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Karen Fisher", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 261364.40466308594, + 191, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Angela Horn", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 261364.40466308594, + 191, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Lauren Hatfield", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 258719.9951171875, + 200, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Tracy Chambers", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 258719.9951171875, + 200, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Tonya Bush", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 258719.9951171875, + 200, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Cynthia Harris", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 258627.6046142578, + 189, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "David Torres", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 258627.6046142578, + 189, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Stacy Ellis", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 257426.39514160156, + 199, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Jason Hill", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 257259.20458984375, + 188, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Douglas Perry", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 256132.79516601562, + 198, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "James Edwards", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 256132.79516601562, + 198, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Crystal Reed", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 255890.8045654297, + 187, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Amanda Fuller", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 255890.8045654297, + 187, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Amber Hernandez", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 254839.1951904297, + 197, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Madison Harper", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 254839.1951904297, + 197, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Rebecca Bradley", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 253154.00451660156, + 185, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Jose Marshall", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 252251.9952392578, + 195, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Tiffany Walters", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 252251.9952392578, + 195, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Tracy Thomas", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 252251.9952392578, + 195, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Robert Bennett", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 251785.6044921875, + 184, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Sarah Scott", + "TXN", + "Texas Instruments Inc.", + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "negative", + 251785.6044921875, + 184, + 1368.4000244140625, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Ashley Walton", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 250958.39526367188, + 194, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "Hailey Thomas", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 250958.39526367188, + 194, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ], + [ + "George Richard", + "GM", + "General Motors Co.", + "GM Signals Trouble as Economic Slowdown Hits Auto Demand", + "negative", + 250958.39526367188, + 194, + 1293.5999755859375, + "2025-09-23T04:29:29.000Z", + null + ] + ] + } + } + ] + } + ], + "response": { + "message": "# Client Exposure to Negative News - Last 24 Hours\n\n## Key Findings\n\nI've analyzed the market for negative news in the past 24 hours and identified two major issues affecting our clients:\n\n1. **Texas Instruments (TXN)** - Major cybersecurity breach with intellectual property at risk\n2. **General Motors (GM)** - Economic slowdown impacting auto demand\n\n## Clients with Highest Exposure\n\n### Texas Instruments (TXN) - Current Price: $1,368.40\n\n| Client Name | Position Value ($) | Shares |\n|-------------|------------------:|-------:|\n| Victoria Schneider | 273,680.00 | 200 |\n| Jillian Davis | 272,311.60 | 199 |\n| Lorraine Gibson | 272,311.60 | 199 |\n| Craig Griffith | 272,311.60 | 199 |\n| Jeffrey Byrd | 270,943.20 | 198 |\n\n### General Motors (GM) - Current Price: $1,293.60\n\n| Client Name | Position Value ($) | Shares |\n|-------------|------------------:|-------:|\n| Lauren Hatfield | 258,720.00 | 200 |\n| Tracy Chambers | 258,720.00 | 200 |\n| Tonya Bush | 258,720.00 | 200 |\n| Stacy Ellis | 257,426.40 | 199 |\n| Douglas Perry | 256,132.80 | 198 |\n\n## Summary\n\nA total of 50 clients have significant exposure to these negative news events. The most affected clients hold positions valued between $250,000 and $274,000. The Texas Instruments cybersecurity breach appears to be affecting more clients with higher position values than the General Motors economic slowdown news.\n\n" + } + }, + { + "id": "4ea485ff-f183-488b-a5de-be7d34fbd766", + "input": { + "message": "Summarize the first article mentioned." + }, + "steps": [ + { + "type": "reasoning", + "reasoning": "I need to find the full content of the article about Texas Instruments (TXN) mentioned in the previous results to provide a summary." + }, + { + "type": "tool_call", + "tool_call_id": "tooluse_Ib9yNGq1RBaata0Ee9I_Sg", + "tool_id": "platform.core.search", + "progression": [ + { + "message": "Selecting the best target for this query" + }, + { + "message": "Selected \"financial_news\" as the next search target" + }, + { + "message": "Thinking about the search strategy to use" + }, + { + "message": "Searching documents for \"TXN Tumbles on Major Cybersecurity Breach, IP at Risk\"" + } + ], + "params": { + "query": "TXN Tumbles on Major Cybersecurity Breach, IP at Risk" + }, + "results": [ + { + "type": "resource", + "data": { + "reference": { + "id": "6c68e55c-b880-4c56-ba22-d9f65abb20c9", + "index": "financial_news" + }, + "partial": true, + "content": { + "highlights": [ + "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "Texas Instruments (TXN) confirmed this morning it has suffered a significant cybersecurity breach, sending", + "The full extent of the breach is currently under investigation.", + "Texas Instruments has engaged leading cybersecurity firms and is cooperating with federal authorities", + "reacting negatively to the potential for reputational damage, competitive disadvantage from stolen IP" + ] + } + } + }, + { + "type": "resource", + "data": { + "reference": { + "id": "efd320dc-7501-4941-87e0-c670fc70808a", + "index": "financial_news" + }, + "partial": true, + "content": { + "highlights": [ + "Walgreens Reels from Major Cybersecurity Breach, Customer Data at Risk", + "Walgreens Boots Alliance Inc. confirmed this morning it has suffered a significant cybersecurity breach", + "The breach could lead to substantial regulatory fines and costly litigation." + ] + } + } + }, + { + "type": "resource", + "data": { + "reference": { + "id": "cc05d0c0-ae02-4c3f-8b3d-7c09d30974e4", + "index": "financial_news" + }, + "partial": true, + "content": { + "highlights": [ + "Tech Sector Scrutinized After Breach at Major QQQ Component", + "The technology sector faces renewed scrutiny after a significant cybersecurity breach was disclosed by", + "Details of the breach are still emerging, but the incident highlights potential vulnerabilities within", + "While the affected company's stock saw a sharp decline, the impact on the broader QQQ ETF has been muted", + "Analysts note the fund's diversification across 100 of the largest non-financial companies on the Nasdaq", + "However, investors remain watchful for any potential contagion effect or a broader reassessment of risk" + ] + } + } + }, + { + "type": "resource", + "data": { + "reference": { + "id": "c69ec94f-506a-4c7a-a891-3e0d4896e7c2", + "index": "financial_news" + }, + "partial": true, + "content": { + "highlights": [ + "Labor disputes at major ports and geopolitical tensions are creating fresh bottlenecks, threatening to", + "The easing of some pressures could help temper inflationary forces, but the new disruptions risk reversing" + ] + } + } + }, + { + "type": "resource", + "data": { + "reference": { + "id": "83525471-2ae5-46fe-a830-39b71babd136", + "index": "financial_news" + }, + "partial": true, + "content": { + "highlights": [ + "Global markets are on edge as escalating geopolitical tensions threaten to unravel established trade", + "Renewed friction between major economic blocs has sparked concerns over fresh supply chain disruptions", + "While the near-term outlook is fraught with risk, ongoing diplomatic talks offer a glimmer of hope, leaving" + ] + } + } + }, + { + "type": "resource", + "data": { + "reference": { + "id": "2fbfc5a3-ea08-489c-a36b-512fdc5ebd90", + "index": "financial_news" + }, + "partial": true, + "content": { + "highlights": [ + "Global markets are on edge as a sudden surge in energy prices threatens to derail economic stability.", + "translated into higher transportation and manufacturing costs, squeezing corporate profit margins across major", + "Consumers are also feeling the pinch at the pump and on their utility bills, stoking fears of a slowdown", + "could reignite stubborn inflationary pressures, potentially complicating central bank policies aimed at" + ] + } + } + }, + { + "type": "resource", + "data": { + "reference": { + "id": "dece1a11-f870-4e5c-8a8d-ad397f915ee7", + "index": "financial_news" + }, + "partial": true, + "content": { + "highlights": [ + "Hopes for a swift return to price stability have faded, as the rising cost of living continues to be a major", + "Renewed market anxiety centers on the possibility of more aggressive interest rate hikes to combat rising", + "prices, a policy that could risk slowing economic growth and increasing the likelihood of a recession" + ] + } + } + }, + { + "type": "resource", + "data": { + "reference": { + "id": "65e2c416-c4a1-4753-90af-b2650a6397af", + "index": "financial_news" + }, + "partial": true, + "content": { + "highlights": [ + "Energy Markets at a Crossroads Amid Supply Jitters", + "A recent dip in crude oil prices has provided some relief to consumers at the pump and eased inflationary", + "pressures on businesses, largely attributed to signs of slowing economic activity in major economies", + "Analysts remain divided on the future trajectory, leaving businesses and policymakers navigating a clouded" + ] + } + } + }, + { + "type": "resource", + "data": { + "reference": { + "id": "cb72648e-5a8c-42e5-9dee-304fd291e632", + "index": "financial_news" + }, + "partial": true, + "content": { + "highlights": [ + "Danaher Faces Patent Challenge Over Biotechnology IP", + "Analysts are monitoring the situation for potential implications on the segment's operations, though", + "the ultimate financial impact remains uncertain at this early stage." + ] + } + } + }, + { + "type": "resource", + "data": { + "reference": { + "id": "91bb392a-7990-4dd9-99af-6904019ab9a8", + "index": "financial_news" + }, + "partial": true, + "content": { + "highlights": [ + "A significant diplomatic breakthrough between major economic powers is sending waves of optimism through", + "Investors are reacting positively to the reduced geopolitical risk, anticipating a period of more stable" + ] + } + } + } + ] + }, + { + "type": "reasoning", + "reasoning": "I need to retrieve the full content of the Texas Instruments cybersecurity breach article to provide a complete summary." + }, + { + "type": "tool_call", + "tool_call_id": "tooluse_Lo_BR2HJSCKkJt-Fe437qw", + "tool_id": "platform.core.get_document_by_id", + "progression": [], + "params": { + "id": "6c68e55c-b880-4c56-ba22-d9f65abb20c9", + "index": "financial_news" + }, + "results": [ + { + "type": "resource", + "data": { + "reference": { + "id": "6c68e55c-b880-4c56-ba22-d9f65abb20c9", + "index": "financial_news" + }, + "partial": false, + "content": { + "article_id": "6c68e55c-b880-4c56-ba22-d9f65abb20c9", + "title": "TXN Tumbles on Major Cybersecurity Breach, IP at Risk", + "content": "Texas Instruments (TXN) confirmed this morning it has suffered a significant cybersecurity breach, sending its stock tumbling in pre-market trading. The semiconductor giant stated that unauthorized actors gained access to its internal servers, with early reports suggesting sensitive intellectual property, including proprietary chip designs and customer data, may have been compromised. The full extent of the breach is currently under investigation.\n\nThe incident raises serious concerns about the security of critical supply chains within the technology sector. Texas Instruments has engaged leading cybersecurity firms and is cooperating with federal authorities. Investors are reacting negatively to the potential for reputational damage, competitive disadvantage from stolen IP, and costly remediation efforts.", + "source": "Reuters", + "published_date": "2025-09-23T04:29:29", + "url": "http://fakenews.com/article/2f4abc0b", + "entities": [ + "Texas Instruments Inc.", + "TXN", + "Technology" + ], + "sentiment": "negative", + "last_updated": "2025-09-23T04:29:29", + "primary_symbol": "TXN", + "company_symbol": null + } + } + } + ] + } + ], + "response": { + "message": "# Summary: TXN Tumbles on Major Cybersecurity Breach, IP at Risk\n\nTexas Instruments (TXN) has confirmed a significant cybersecurity breach where unauthorized actors gained access to the company's internal servers. According to the article published on September 23, 2025:\n\n## Key Points:\n\n- Unauthorized actors accessed Texas Instruments' internal servers\n- Early reports suggest sensitive intellectual property was compromised, including:\n - Proprietary chip designs\n - Customer data\n\n- The full extent of the breach is still under investigation\n- Texas Instruments has:\n - Engaged leading cybersecurity firms\n - Started cooperating with federal authorities\n\n## Market Impact:\n\n- TXN stock tumbled in pre-market trading\n- Investors are concerned about:\n - Potential reputational damage\n - Competitive disadvantage from stolen intellectual property\n - Costly remediation efforts\n\nThe incident has raised serious concerns about security vulnerabilities in critical supply chains within the technology sector." + } + } + ] + } + }, + "metadata": { + "application/json": { + "expanded": false, + "root": "root" + } + } + } + ] + } + ] +} \ No newline at end of file