← Back to Cookbook
hubspot dynamic multi agent system
Details
File: mistral/agents/non_framework/hubspot_dynamic_multi_agent/hubspot_dynamic_multi_agent_system.ipynb
Type: Jupyter Notebook
Use Cases: Agents
Content
Notebook content (JSON format):
{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "zHuUcZDooiRh" }, "source": [ "# HubSpot Dynamic Multi-Agent System with Magistral Reasoning\n", "\n", "<a href=\"https://colab.research.google.com/github/mistralai/cookbook/blob/main/mistral/agents/non_framework/hubspot_dynamic_multi_agent/hubspot_dynamic_multi_agent_system.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>\n", "\n", "This cookbook demonstrates the power of Magistral reasoning model combined with HubSpot CRM integration to create an intelligent, multi-agent system that can understand complex business queries and execute sophisticated CRM operations automatically.\n", "\\\n", "The system transforms natural language business questions into actionable insights and automated CRM updates, showcasing how advanced AI reasoning can streamline sales operations and strategic decision-making.\n", "\n", "\n", "\n", "## Problem Statement\n", "\n", "### Traditional CRM Challenges\n", "Modern sales and marketing teams face several critical challenges when working with CRM systems like HubSpot:\n", "\n", "**Manual Data Analysis:** Teams spend hours manually analyzing deals, contacts, and companies to extract insights\n", "**Complex Query Processing:** Business stakeholders struggle to get answers to multi-faceted questions that require data from multiple CRM objects\n", "**Strategic Planning:** Market analysis and expansion planning requires combining CRM data with business intelligence in ways that aren't natively supported\n", "\n", "### Sample Query\n", "\n", "\"Assign priorities to all deals based on deal value\"\n", "\n", "These queries require:\n", "\n", "- Understanding business context\n", "- Analyzing multiple data sources\n", "- Applying business logic\n", "- Generating actionable recommendations\n", "- Sometimes updating CRM records automatically" ] }, { "cell_type": "markdown", "metadata": { "id": "b394NlampCuI" }, "source": [ "## Solution Architecture\n", "\n", "**Core Innovation:** Magistral Reasoning + HubSpot Integration + Multi-Agent Orchestration\n", "\n", "Our solution combines **Mistral's Magistral reasoning model** with **HubSpot's comprehensive CRM API** through a sophisticated multi-agent system that can:\n", "\n", "- **Understand** complex business queries using Magistral's advanced reasoning capabilities\n", "- **Plan** multi-step execution strategies with dynamically created specialized agents\n", "- **Execute** both data analysis and CRM updates through coordinated agent workflows\n", "- **Synthesize** results into actionable business insights with strategic recommendations\n", "\n", "### AgentOrchestrator\n", "**Master coordinator** that manages the entire multi-agent workflow and HubSpot integration. Orchestrates the complete flow from query analysis through sub-agent execution to final synthesis, while managing agent lifecycle and data connectivity.\n", "\n", "### LeadAgent\n", "Powered by **Magistral reasoning model** with `<think>` pattern processing, the Lead Agent performs sophisticated query analysis to understand business intent, determine data requirements, and create detailed execution plans specifying which sub-agents to create dynamically.\n", "\n", "### Dynamic Sub-Agents\n", "Sub-agents are **created on-the-fly** based on specific query requirements - not pre-defined templates. Each agent is dynamically generated with specialized roles (e.g., priority_calculator, market_analyzer, deals_updater), specific tasks, and targeted data access patterns using **Mistral Small** for fast execution.\n", "\n", "### HubSpot API Connector\n", "Dedicated connector providing comprehensive access to CRM data and operations:\n", "- **Property Discovery:** Automatically maps all available HubSpot fields and valid values\n", "- **Data Fetching:** Retrieves deals, contacts, and companies with full property sets\n", "- **Batch Updates:** Efficiently updates multiple records in batches of 100\n", "\n", "### SynthesisAgent\n", "**Final orchestrator** that combines all sub-agent results into coherent, actionable business insights using **Mistral Small**. Transforms technical agent outputs into user-friendly responses with strategic recommendations and next steps." ] }, { "cell_type": "markdown", "metadata": { "id": "BGu2JLH4Ksum" }, "source": [ "" ] }, { "cell_type": "markdown", "metadata": { "id": "YIALi-p_qZ5j" }, "source": [ "#### Installation\n", "\n", "We need `hubspot-api-client` and `mistralai` packages for the demonstration." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "HFB29XnAL-ge", "outputId": "7872a545-4c7b-426e-8eb0-ea0fd7ae6a3b" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Collecting hubspot-api-client\n", " Downloading hubspot_api_client-12.0.0-py3-none-any.whl.metadata (9.3 kB)\n", "Collecting mistralai\n", " Downloading mistralai-1.9.3-py3-none-any.whl.metadata (37 kB)\n", "Requirement already satisfied: requests>=2.31.0 in /usr/local/lib/python3.11/dist-packages (from hubspot-api-client) (2.32.3)\n", "Requirement already satisfied: urllib3<3.0,>=1.15 in /usr/local/lib/python3.11/dist-packages (from hubspot-api-client) (2.5.0)\n", "Requirement already satisfied: six<2.0,>=1.10 in /usr/local/lib/python3.11/dist-packages (from hubspot-api-client) (1.17.0)\n", "Requirement already satisfied: certifi>=2023.1.1 in /usr/local/lib/python3.11/dist-packages (from hubspot-api-client) (2025.7.14)\n", "Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.11/dist-packages (from hubspot-api-client) (2.9.0.post0)\n", "Collecting eval-type-backport>=0.2.0 (from mistralai)\n", " Downloading eval_type_backport-0.2.2-py3-none-any.whl.metadata (2.2 kB)\n", "Requirement already satisfied: httpx>=0.28.1 in /usr/local/lib/python3.11/dist-packages (from mistralai) (0.28.1)\n", "Requirement already satisfied: pydantic>=2.10.3 in /usr/local/lib/python3.11/dist-packages (from mistralai) (2.11.7)\n", "Requirement already satisfied: typing-inspection>=0.4.0 in /usr/local/lib/python3.11/dist-packages (from mistralai) (0.4.1)\n", "Requirement already satisfied: anyio in /usr/local/lib/python3.11/dist-packages (from httpx>=0.28.1->mistralai) (4.9.0)\n", "Requirement already satisfied: httpcore==1.* in /usr/local/lib/python3.11/dist-packages (from httpx>=0.28.1->mistralai) (1.0.9)\n", "Requirement already satisfied: idna in /usr/local/lib/python3.11/dist-packages (from httpx>=0.28.1->mistralai) (3.10)\n", "Requirement already satisfied: h11>=0.16 in /usr/local/lib/python3.11/dist-packages (from httpcore==1.*->httpx>=0.28.1->mistralai) (0.16.0)\n", "Requirement already satisfied: annotated-types>=0.6.0 in /usr/local/lib/python3.11/dist-packages (from pydantic>=2.10.3->mistralai) (0.7.0)\n", "Requirement already satisfied: pydantic-core==2.33.2 in /usr/local/lib/python3.11/dist-packages (from pydantic>=2.10.3->mistralai) (2.33.2)\n", "Requirement already satisfied: typing-extensions>=4.12.2 in /usr/local/lib/python3.11/dist-packages (from pydantic>=2.10.3->mistralai) (4.14.1)\n", "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.11/dist-packages (from requests>=2.31.0->hubspot-api-client) (3.4.2)\n", "Requirement already satisfied: sniffio>=1.1 in /usr/local/lib/python3.11/dist-packages (from anyio->httpx>=0.28.1->mistralai) (1.3.1)\n", "Downloading hubspot_api_client-12.0.0-py3-none-any.whl (4.3 MB)\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m4.3/4.3 MB\u001b[0m \u001b[31m43.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[?25hDownloading mistralai-1.9.3-py3-none-any.whl (426 kB)\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m426.3/426.3 kB\u001b[0m \u001b[31m17.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[?25hDownloading eval_type_backport-0.2.2-py3-none-any.whl (5.8 kB)\n", "Installing collected packages: eval-type-backport, hubspot-api-client, mistralai\n", "Successfully installed eval-type-backport-0.2.2 hubspot-api-client-12.0.0 mistralai-1.9.3\n" ] } ], "source": [ "!pip install hubspot-api-client==\"12.0.0\" mistralai==\"1.9.3\"" ] }, { "cell_type": "markdown", "metadata": { "id": "vSlyds7vqorQ" }, "source": [ "#### Imports" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "id": "68y1SSvsMFo3" }, "outputs": [], "source": [ "import requests\n", "import json\n", "from mistralai import Mistral, ThinkChunk, TextChunk\n", "from datetime import datetime, timedelta\n", "from typing import Dict, List, Any, Optional\n", "import re\n" ] }, { "cell_type": "markdown", "metadata": { "id": "Kg0JrdH4qqIL" }, "source": [ "#### Setup API Keys" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "id": "KPUEXAmVMMvH" }, "outputs": [], "source": [ "HUBSPOT_API_KEY = \"<YOUR HUBSPOT API KEY>\" # Replace with your HubSpot API key\n", "MISTRAL_API_KEY = \"<YOUR MISTRAL API KEY>\" # Get it from https://console.mistral.ai/api-keys" ] }, { "cell_type": "markdown", "metadata": { "id": "DVqq7xT1quWv" }, "source": [ "#### Setup MistralAI Client" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "id": "hAULb_8Squ6_" }, "outputs": [], "source": [ "mistral_client = Mistral(api_key=MISTRAL_API_KEY)" ] }, { "cell_type": "markdown", "metadata": { "id": "qZhFwvYarOct" }, "source": [ "#### HubSpot API connector\n", "\n", "- `get_data`: Fetches CRM data from HubSpot API, Retrieves deals, contacts, and companies data for the analysis.\n", "\n", "- `batch_update`: Performs batch updates to HubSpot records, the updates and writes them back to HubSpot in efficient batches of 100 records.\n", "\n", "- `get_properties`: Automatically fetches and formats all HubSpot deal, contact, and company properties, including valid values and dropdown options, so agents can update data reliably without errors.\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "id": "a2xWb8VXMAa0" }, "outputs": [], "source": [ "class HubSpotConnector:\n", " \"\"\"Handles all HubSpot API operations\"\"\"\n", "\n", " def __init__(self, api_key: str):\n", " self.api_key = api_key\n", " self.base_url = \"https://api.hubapi.com/crm/v3/objects\"\n", " self.headers = {\"Authorization\": f\"Bearer {api_key}\"}\n", "\n", " def get_properties(self) -> Dict:\n", " \"\"\"Load all HubSpot properties\"\"\"\n", " print(\"📡 HubSpotConnector: Loading properties...\")\n", " properties = {}\n", "\n", " for obj_type in ['deals', 'contacts', 'companies']:\n", " url = f\"https://api.hubapi.com/crm/v3/properties/{obj_type}\"\n", " response = requests.get(url, headers=self.headers)\n", "\n", " if response.status_code == 200:\n", " props = response.json()['results']\n", " prop_list = []\n", " for prop in sorted(props, key=lambda x: x['name']):\n", " prop_str = f\"'{prop['name']}' - {prop['label']}\"\n", " if 'options' in prop and prop['options']:\n", " valid_values = [opt['value'] for opt in prop['options']]\n", " prop_str += f\" | Valid values: {valid_values}\"\n", " prop_list.append(prop_str)\n", "\n", " properties[obj_type] = prop_list\n", "\n", " print(f\"✅ HubSpotConnector: Loaded properties for {len(properties)} object types\")\n", " return properties\n", "\n", " def get_data(self, object_type: str) -> List[Dict]:\n", " \"\"\"Fetch data from HubSpot\"\"\"\n", " print(f\"📡 HubSpotConnector: Fetching {object_type} data...\")\n", "\n", " url = f\"{self.base_url}/{object_type}\"\n", " params = {\"limit\": 100}\n", " all_data = []\n", "\n", " while url:\n", " response = requests.get(url, headers=self.headers, params=params)\n", " if response.status_code != 200:\n", " raise Exception(f\"HubSpot API error: {response.text}\")\n", "\n", " data = response.json()\n", " all_data.extend(data.get(\"results\", []))\n", " url = data.get(\"paging\", {}).get(\"next\", {}).get(\"link\")\n", " params = {}\n", "\n", " print(f\"✅ HubSpotConnector: Loaded {len(all_data)} {object_type}\")\n", " return all_data\n", "\n", " def batch_update(self, updates: Dict) -> None:\n", " \"\"\"Perform batch updates to HubSpot\"\"\"\n", " for object_type, update_list in updates.items():\n", " if not update_list:\n", " continue\n", "\n", " print(f\"📡 HubSpotConnector: Updating {len(update_list)} {object_type}...\")\n", "\n", " url = f\"{self.base_url}/{object_type}/batch/update\"\n", " headers = {**self.headers, \"Content-Type\": \"application/json\"}\n", "\n", " # Process in batches of 100\n", " for i in range(0, len(update_list), 100):\n", " batch = update_list[i:i+100]\n", " payload = {\"inputs\": batch}\n", "\n", " response = requests.post(url, headers=headers, json=payload)\n", " if response.status_code not in [200, 202]:\n", " raise Exception(f\"HubSpot update error: {response.text}\")\n", "\n", " print(f\"✅ HubSpotConnector: {object_type} updates completed\")" ] }, { "cell_type": "markdown", "metadata": { "id": "QrEsrWZFsvOt" }, "source": [ "#### Magistral (reasoning) and Mistral small LLM functions\n", "\n", "- `magistral_reasoning`: Uses Magistral reasoning model for complex query analysis and execution planning with thinking process.\n", "\n", "- `mistral_small_execution`: Uses Mistral Small model for sub-agent task execution." ] }, { "cell_type": "code", "execution_count": 125, "metadata": { "id": "AR7klhpLsr9R" }, "outputs": [], "source": [ "def magistral_reasoning(prompt: str) -> Dict[str, str]:\n", " \"\"\"Use reasoning model for query analysis and planning\"\"\"\n", " response = mistral_client.chat.complete(\n", " model=\"magistral-medium-latest\",\n", " messages=[{\"role\": \"user\", \"content\": prompt}]\n", " )\n", "\n", " content = response.choices[0].message.content\n", "\n", " reasoning = \"\"\n", " conclusion = \"\"\n", "\n", " for r in content:\n", " if isinstance(r, ThinkChunk):\n", " reasoning = r.thinking[0].text\n", " elif isinstance(r, TextChunk):\n", " conclusion = r.text\n", "\n", " return {\n", " \"reasoning\": reasoning,\n", " \"conclusion\": conclusion\n", " }\n", "\n", "def mistral_small_execution(prompt: str) -> str:\n", " \"\"\"Use Mistral Small for content generation\"\"\"\n", " response = mistral_client.chat.complete(\n", " model=\"mistral-small-latest\",\n", " messages=[{\"role\": \"user\", \"content\": prompt}]\n", " )\n", " return response.choices[0].message.content" ] }, { "cell_type": "markdown", "metadata": { "id": "dsl_i6_80vc3" }, "source": [ "#### LeadAgent\n", "\n", "**Powered by Magistral reasoning model** for sophisticated query analysis and execution planning\n", "\n", "- `analyze_query`: Uses Magistral's `<think>` pattern to understand business intent, determine data requirements, and create detailed execution plans with dynamic sub-agent specifications\n", "- Determines whether queries require read-only analysis or write-back operations to HubSpot\n" ] }, { "cell_type": "code", "execution_count": 126, "metadata": { "id": "Z-WVJv8azNzC" }, "outputs": [], "source": [ "class LeadAgent:\n", " \"\"\"Lead Agent powered by Magistral reasoning model for query analysis and planning\"\"\"\n", "\n", " def __init__(self, hubspot_properties):\n", " self.hubspot_properties = hubspot_properties\n", " self.name = \"LeadAgent\"\n", "\n", " def analyze_query(self, query: str) -> Dict:\n", " \"\"\"Analyze query using Magistral reasoning and create execution plan\"\"\"\n", " print(f\"🧠 {self.name}: Analyzing query with Magistral reasoning...\")\n", "\n", " analysis_prompt = f\"\"\"\n", " Analyze this HubSpot query and create a detailed execution plan based on different hubspot properties provided by following the shared rules:\n", "\n", " HUBSPOT_PROPERTIES: {self.hubspot_properties}\n", "\n", " QUERY: {query}\n", "\n", " RULES:\n", " 1. What is the user asking for?\n", " 2. Is this a read-only query or does it require HubSpot updates?\n", " 3. What sub-agents are needed to accomplish this?\n", " 4. What HubSpot data is required?\n", " 5. What's the execution sequence?\n", " 6. What should be the final output format?\n", " 7. Query can also be combination of read-only and write-back.\n", " 8. Query is read-only if it requires data read from HubSpot.\n", " 9. Query is write-back if it requires an update to existing values or writing/ assigning new values.\n", " 10. In the final conclusion just give only one JSON string nothing else. I don't need any explanation.\n", "\n", " Provide a JSON execution plan with:\n", " {{\n", " \"sub_agents\": [\n", " {{\n", " \"name\": \"agent_name\",\n", " \"task\": \"specific task description\",\n", " \"task_type\": \"read_only\" or \"write_back\",\n", " \"input_data\": [\"deals\", \"contacts\", \"companies\"],\n", " \"output_format\": \"expected output\"\n", " }}\n", " ]\n", " }}\n", " \"\"\"\n", "\n", " # Use existing magistral_reasoning function\n", " analysis = magistral_reasoning(analysis_prompt)\n", "\n", " try:\n", " # Extract JSON execution plan from conclusion\n", " json_match = re.search(r'\\{.*\\}', analysis[\"conclusion\"], re.DOTALL)\n", " if json_match:\n", " execution_plan = json.loads(json_match.group(0))\n", " else:\n", " raise ValueError(\"No JSON found in analysis\")\n", " except Exception as e:\n", " print(f\"⚠️ {self.name}: JSON parsing failed, using fallback plan\")\n", " execution_plan = {\n", " \"sub_agents\": [{\n", " \"name\": \"general_analyzer\",\n", " \"task\": query,\n", " \"task_type\": \"read_only\",\n", " \"input_data\": [\"deals\", \"contacts\", \"companies\"],\n", " \"output_format\": \"summary\"\n", " }]\n", " }\n", "\n", " print(f\"✅ {self.name}: Plan created - {len(execution_plan['sub_agents'])} sub-agents needed\")\n", "\n", " return {\n", " \"reasoning\": analysis[\"reasoning\"],\n", " \"execution_plan\": execution_plan,\n", " \"conclusion\": analysis[\"conclusion\"]\n", " }" ] }, { "cell_type": "markdown", "metadata": { "id": "64y6BK0O02gY" }, "source": [ "#### SubAgent\n", "\n", "**Dynamic agents created on-the-fly** based on query complexity and requirements\n", "\n", "- `execute`: Uses Mistral Small for fast task execution including data analysis, business logic application, and CRM updates\n", "- Specialized roles generated automatically (e.g., priority_calculator, market_analyzer, deals_updater)\n", "- Handles both read-only operations and write-back operations with proper HubSpot property validation\n" ] }, { "cell_type": "code", "execution_count": 127, "metadata": { "id": "Evv58qR1zScL" }, "outputs": [], "source": [ "class SubAgent:\n", " \"\"\"Dynamic Sub-Agent created on-the-fly for specific tasks\"\"\"\n", "\n", " def __init__(self, name: str, task: str, task_type: str, input_data: List[str],\n", " output_format: str):\n", " self.name = name\n", " self.task = task\n", " self.task_type = task_type\n", " self.input_data = input_data\n", " self.output_format = output_format\n", "\n", " def execute(self, data: Dict, properties_context: str, hubspot_updater=None) -> Dict:\n", " \"\"\"Execute the assigned task\"\"\"\n", " print(f\"🤖 {self.name} ({self.task_type}): Executing task...\")\n", "\n", " if self.task_type == 'read_only':\n", " agent_prompt = f\"\"\"\n", " You are a {self.name} agent.\n", "\n", " TASK: {self.task}\n", "\n", " AVAILABLE HUBSPOT PROPERTIES:\n", " {properties_context}\n", "\n", " DATA AVAILABLE:\n", " {json.dumps(data, indent=2)}\n", "\n", " OUTPUT FORMAT: {self.output_format}\n", "\n", " Provide your analysis only based on the available data.\n", " \"\"\"\n", " else: # write_back\n", " agent_prompt = f\"\"\"\n", " You are a {self.name} agent.\n", "\n", " TASK: {self.task}\n", "\n", " AVAILABLE HUBSPOT PROPERTIES:\n", " {properties_context}\n", "\n", " DATA AVAILABLE:\n", " {json.dumps(data, indent=2)}\n", "\n", " CRITICAL: Use exact HubSpot property names from the list above in your JSON output.\n", "\n", " OUTPUT FORMAT: JSON format with the properties to be written to HubSpot\n", "\n", " Provide updates using exact HubSpot property names.\n", " \"\"\"\n", "\n", " # Use existing mistral_small_execution function\n", " result = mistral_small_execution(agent_prompt)\n", "\n", " # Handle write-back operations\n", " if self.task_type == 'write_back' and hubspot_updater:\n", " try:\n", " json_match = re.search(r'\\{.*\\}', result, re.DOTALL)\n", " if json_match:\n", " updates = json.loads(json_match.group(0))\n", " hubspot_updater.batch_update(updates)\n", " print(f\"✅ {self.name}: Successfully updated HubSpot records\")\n", " except Exception as e:\n", " print(f\"❌ {self.name}: Update failed - {str(e)}\")\n", " return {\"status\": \"error\", \"error\": str(e), \"raw_result\": result}\n", "\n", " print(f\"✅ {self.name}: Task completed successfully\")\n", " return {\"status\": \"success\", \"result\": result}" ] }, { "cell_type": "markdown", "metadata": { "id": "TGI61vGX07CH" }, "source": [ "#### SynthesisAgent\n", "\n", "**Final orchestrator** that combines all sub-agent results into coherent business insights\n", "\n", "- `synthesize`: Uses Mistral Small to create user-friendly responses with actionable recommendations and next steps\n", "- Transforms technical agent outputs into executive-ready summaries and strategic guidance\n" ] }, { "cell_type": "code", "execution_count": 128, "metadata": { "id": "AciRA7jbzVF6" }, "outputs": [], "source": [ "class SynthesisAgent:\n", " \"\"\"Final agent to synthesize all results into user-friendly response\"\"\"\n", "\n", " def __init__(self):\n", " self.name = \"SynthesisAgent\"\n", "\n", " def synthesize(self, query: str, sub_agent_results: List[Dict], execution_plan: Dict) -> str:\n", " \"\"\"Combine all sub-agent results into final answer\"\"\"\n", " print(f\"🔄 {self.name}: Synthesizing results from {len(sub_agent_results)} agents...\")\n", "\n", " # Prepare context from all sub-agent results\n", " results_context = \"\"\n", " for result in sub_agent_results:\n", " results_context += f\"\\n{result['agent'].upper()} ({result['task_type']}):\\n\"\n", " if result['result']['status'] == 'success':\n", " results_context += f\"{result['result']['result']}\\n\"\n", " else:\n", " results_context += f\"Error: {result['result'].get('error', 'Unknown error')}\\n\"\n", " results_context += \"---\\n\"\n", "\n", " synthesis_prompt = f\"\"\"\n", " You are a final synthesizer agent. Create a comprehensive, user-friendly response based on all sub-agent results.\n", "\n", " ORIGINAL QUERY: {query}\n", "\n", " SUB-AGENT RESULTS:\n", " {results_context}\n", "\n", " TASK: Synthesize all the above results into a clear, actionable response for the user.\n", "\n", " Guidelines:\n", " 1. Start with a direct answer to the user's query\n", " 2. Include key insights and findings\n", " 3. If updates were made, summarize what was changed\n", " 4. Provide actionable next steps if relevant\n", " 5. Keep it concise but comprehensive\n", " 6. Use a professional but friendly tone\n", "\n", " Provide the final synthesized response:\n", " \"\"\"\n", "\n", " # Use existing mistral_small_execution function\n", " final_answer = mistral_small_execution(synthesis_prompt)\n", " print(f\"✅ {self.name}: Final answer synthesized\")\n", "\n", " return final_answer" ] }, { "cell_type": "markdown", "metadata": { "id": "R4bsSkzM0_jo" }, "source": [ "#### AgentOrchestrator\n", "\n", "**Master coordinator** that manages the entire multi-agent workflow and HubSpot integration\n", "\n", "- `process_query`: Orchestrates the complete flow from query analysis through sub-agent execution to final synthesis\n", "- Manages agent lifecycle, data flow between agents, and HubSpot connectivity\n", "- Provides rich logging and monitoring of the multi-agent process" ] }, { "cell_type": "code", "execution_count": 129, "metadata": { "id": "VlVUKSS5zY1p" }, "outputs": [], "source": [ "class AgentOrchestrator:\n", " \"\"\"Main orchestrator that coordinates all agents\"\"\"\n", "\n", " def __init__(self, hubspot_api_key: str, mistral_api_key: str):\n", " # Initialize global mistral client for existing functions\n", " global mistral_client\n", " mistral_client = Mistral(api_key=mistral_api_key)\n", "\n", " # Initialize HubSpot connector\n", " self.hubspot_connector = HubSpotConnector(hubspot_api_key)\n", "\n", " # Load HubSpot data and properties\n", " self.hubspot_properties = self.hubspot_connector.get_properties()\n", " self.hubspot_data = {\n", " \"deals\": self.hubspot_connector.get_data(\"deals\"),\n", " \"contacts\": self.hubspot_connector.get_data(\"contacts\"),\n", " \"companies\": self.hubspot_connector.get_data(\"companies\")\n", " }\n", "\n", " # Initialize agents\n", " self.lead_agent = LeadAgent(self.hubspot_properties)\n", " self.synthesis_agent = SynthesisAgent()\n", " self.active_sub_agents = []\n", "\n", " print(f\"🚀 AgentOrchestrator: System initialized with {sum(len(data) for data in self.hubspot_data.values())} HubSpot records\")\n", "\n", " def process_query(self, query: str) -> Dict:\n", " \"\"\"Main method to process user queries through multi-agent workflow\"\"\"\n", " print(f\"\\n🎯 Processing Query: {query[:100]}...\")\n", " print(\"=\" * 80)\n", "\n", " # Step 1: Lead Agent analyzes query using Magistral reasoning\n", " analysis = self.lead_agent.analyze_query(query)\n", " execution_plan = analysis[\"execution_plan\"]\n", "\n", " # Step 2: Create and execute sub-agents dynamically\n", " sub_agent_results = []\n", " self.active_sub_agents = []\n", "\n", " for agent_config in execution_plan[\"sub_agents\"]:\n", " # Create sub-agent dynamically\n", " sub_agent = SubAgent(\n", " name=agent_config[\"name\"],\n", " task=agent_config[\"task\"],\n", " task_type=agent_config[\"task_type\"],\n", " input_data=agent_config[\"input_data\"],\n", " output_format=agent_config[\"output_format\"]\n", " )\n", "\n", " self.active_sub_agents.append(sub_agent)\n", "\n", " # Prepare data and context for this sub-agent\n", " agent_data = {data_type: self.hubspot_data.get(data_type, [])\n", " for data_type in agent_config[\"input_data\"]}\n", "\n", " # Build properties context\n", " properties_context = \"\"\n", " for data_type in agent_config[\"input_data\"]:\n", " if data_type in self.hubspot_properties:\n", " properties_context += f\"\\n{data_type.upper()} PROPERTIES:\\n\"\n", " properties_context += \"\\n\".join(self.hubspot_properties[data_type])\n", " properties_context += \"\\n\"\n", "\n", " # Execute sub-agent using mistral_small_execution\n", " result = sub_agent.execute(agent_data, properties_context, self.hubspot_connector)\n", " sub_agent_results.append({\n", " \"agent\": sub_agent.name,\n", " \"task_type\": sub_agent.task_type,\n", " \"result\": result\n", " })\n", "\n", " # Step 3: Synthesis Agent creates final answer using mistral_small_execution\n", " final_answer = self.synthesis_agent.synthesize(query, sub_agent_results, execution_plan)\n", "\n", " print(\"=\" * 80)\n", " print(\"✨ Query processing completed!\")\n", "\n", " return {\n", " \"query\": query,\n", " \"reasoning\": analysis[\"reasoning\"],\n", " \"execution_plan\": execution_plan,\n", " \"sub_agent_results\": sub_agent_results,\n", " \"active_agents\": [agent.name for agent in self.active_sub_agents],\n", " \"final_answer\": final_answer\n", " }" ] }, { "cell_type": "markdown", "metadata": { "id": "gPBAxJLetVex" }, "source": [ "\n", "#### Initialize the multi-agent system" ] }, { "cell_type": "code", "execution_count": 140, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "x-z1uHzKV-kF", "outputId": "44ee2d0b-c6dc-4211-ad4e-16382bee7af5" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "📡 HubSpotConnector: Loading properties...\n", "✅ HubSpotConnector: Loaded properties for 3 object types\n", "📡 HubSpotConnector: Fetching deals data...\n", "✅ HubSpotConnector: Loaded 5 deals\n", "📡 HubSpotConnector: Fetching contacts data...\n", "✅ HubSpotConnector: Loaded 5 contacts\n", "📡 HubSpotConnector: Fetching companies data...\n", "✅ HubSpotConnector: Loaded 5 companies\n", "🚀 AgentOrchestrator: System initialized with 15 HubSpot records\n" ] } ], "source": [ "orchestrator = AgentOrchestrator(\n", " hubspot_api_key=HUBSPOT_API_KEY,\n", " mistral_api_key=MISTRAL_API_KEY\n", " )\n" ] }, { "cell_type": "markdown", "metadata": { "id": "7QrNTfJXtRA5" }, "source": [ "#### Test Queries" ] }, { "cell_type": "markdown", "metadata": { "id": "mmVIrt8yteMX" }, "source": [ "##### Query-1" ] }, { "cell_type": "code", "execution_count": 141, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "2Y_eWfEtWBPR", "outputId": "4fa2bfeb-beb3-49f7-c3b3-39d76bc9c2a9" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "🎯 Processing Query: Assign priorities to all deals based on deal value....\n", "================================================================================\n", "🧠 LeadAgent: Analyzing query with Magistral reasoning...\n", "✅ LeadAgent: Plan created - 2 sub-agents needed\n", "🤖 deal_data_fetcher (read_only): Executing task...\n", "✅ deal_data_fetcher: Task completed successfully\n", "🤖 priority_assigner (write_back): Executing task...\n", "📡 HubSpotConnector: Updating 5 deals...\n", "✅ HubSpotConnector: deals updates completed\n", "✅ priority_assigner: Successfully updated HubSpot records\n", "✅ priority_assigner: Task completed successfully\n", "🔄 SynthesisAgent: Synthesizing results from 2 agents...\n", "✅ SynthesisAgent: Final answer synthesized\n", "================================================================================\n", "✨ Query processing completed!\n" ] } ], "source": [ "query = \"Assign priorities to all deals based on deal value.\"\n", "\n", "result = orchestrator.process_query(query)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### HubSpot status before updation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### HubSpot status after updation\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "id": "M-f2f-E5JhjQ" }, "source": [ "##### Dynamically Created Agents" ] }, { "cell_type": "code", "execution_count": 142, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 80 }, "id": "ybA7pQ6iJm7O", "outputId": "65deb664-91cf-4c00-c4a1-5efeae600954" }, "outputs": [ { "data": { "text/markdown": [ "1. deal_data_fetcher\n", "2. priority_assigner" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "agents = '\\n'.join([f\"{i + 1}. {agent}\" for i, agent in enumerate(result['active_agents'])])\n", "\n", "display(Markdown(agents))" ] }, { "cell_type": "markdown", "metadata": { "id": "dcOuKz9XJ4jI" }, "source": [ "##### Answer" ] }, { "cell_type": "code", "execution_count": 143, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 495 }, "id": "OL0pjR5w_3Ox", "outputId": "de5d2ed1-a214-4944-cda0-e3bceceaa2bb" }, "outputs": [ { "data": { "text/markdown": [ "**Final Synthesized Response:**\n", "\n", "**Deal Priorities Assigned Based on Value:**\n", "We’ve successfully assigned priorities to all deals based on their values. Here’s the breakdown:\n", "\n", "1. **High Priority (1 deal):**\n", " - **Enterprise Ltd - Platform Integration** ($200,000)\n", " - *Reason:* Value exceeds $200,000.\n", "\n", "2. **Medium Priority (2 deals):**\n", " - **Global Solutions - Sales Training** ($125,000)\n", " - **Acme Corp - CRM Implementation** ($85,000)\n", " - *Reason:* Values fall between $50,000–$199,999.\n", "\n", "3. **Low Priority (2 deals):**\n", " - **StartupXYZ - Consulting Services** ($25,000)\n", " - **TechStart Inc - Marketing Automation** ($45,000)\n", " - *Reason:* Values below $50,000.\n", "\n", "**Key Insights:**\n", "- The highest-value deal ($200,000) is prioritized as *high*.\n", "- Medium-priority deals are in the mid-range value tier.\n", "- Low-priority deals are smaller in value but may still be important for long-term growth.\n", "\n", "**Next Steps:**\n", "- Review the priorities to ensure alignment with business goals.\n", "- Focus resources on high/medium-priority deals to maximize revenue impact.\n", "- Monitor low-priority deals for potential upsell opportunities.\n", "\n", "Let us know if you’d like to adjust the criteria or need further analysis!\n", "\n", "---\n", "*All updates have been applied to your CRM system.*" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from IPython.display import display, Markdown, Latex\n", "display(Markdown(result['final_answer']))" ] }, { "cell_type": "markdown", "metadata": { "id": "o0GBx1ewtg8t" }, "source": [ "##### Query-2" ] }, { "cell_type": "code", "execution_count": 131, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "A1tx87PKXZUy", "outputId": "6e63f9ad-aaba-4ca5-df55-ebe3ce3e3691" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "🎯 Processing Query: We're considering expanding into three new industry verticals and need comprehensive market\n", " inte...\n", "================================================================================\n", "🧠 LeadAgent: Analyzing query with Magistral reasoning...\n", "✅ LeadAgent: Plan created - 6 sub-agents needed\n", "🤖 Customer Success Analysis Agent (read_only): Executing task...\n", "✅ Customer Success Analysis Agent: Task completed successfully\n", "🤖 Market Opportunity Analysis Agent (read_only): Executing task...\n", "✅ Market Opportunity Analysis Agent: Task completed successfully\n", "🤖 Competitive Landscape Analysis Agent (read_only): Executing task...\n", "✅ Competitive Landscape Analysis Agent: Task completed successfully\n", "🤖 Ideal Customer Profile Agent (read_only): Executing task...\n", "✅ Ideal Customer Profile Agent: Task completed successfully\n", "🤖 Market Size and Penetration Agent (read_only): Executing task...\n", "✅ Market Size and Penetration Agent: Task completed successfully\n", "🤖 Market Entry Strategy Agent (read_only): Executing task...\n", "✅ Market Entry Strategy Agent: Task completed successfully\n", "🔄 SynthesisAgent: Synthesizing results from 6 agents...\n", "✅ SynthesisAgent: Final answer synthesized\n", "================================================================================\n", "✨ Query processing completed!\n" ] } ], "source": [ "query = \"\"\"We're considering expanding into three new industry verticals and need comprehensive market\n", " intelligence to inform our go-to-market strategy. Analyze our current customer base to identify\n", " patterns in successful account profiles, understand the characteristics that predict customer\n", " success, and use these insights to evaluate market opportunities. The analysis should identify\n", " which industries show the strongest fit with our solution, what use cases resonate most effectively,\n", " and what competitive landscape we would face. Develop ideal customer profiles for each target\n", " market, estimate market size and penetration potential, and create a prioritized market entry\n", " strategy with resource requirements and timeline projections for successful market penetration.\"\"\"\n", "\n", "result = orchestrator.process_query(query)" ] }, { "cell_type": "markdown", "metadata": { "id": "LsxvqHxHJbhx" }, "source": [ "##### Dynamically Created Agents" ] }, { "cell_type": "code", "execution_count": 139, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 149 }, "id": "O70MJbNs0NcV", "outputId": "4738ec73-ac2d-48cf-8261-b95313f8f0c0" }, "outputs": [ { "data": { "text/markdown": [ "1. Customer Success Analysis Agent\n", "2. Market Opportunity Analysis Agent\n", "3. Competitive Landscape Analysis Agent\n", "4. Ideal Customer Profile Agent\n", "5. Market Size and Penetration Agent\n", "6. Market Entry Strategy Agent" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "agents = '\\n'.join([f\"{i + 1}. {agent}\" for i, agent in enumerate(result['active_agents'])])\n", "\n", "display(Markdown(agents))" ] }, { "cell_type": "markdown", "metadata": { "id": "LUJPQxdUJ-J_" }, "source": [ "##### Answer" ] }, { "cell_type": "code", "execution_count": 132, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 956 }, "id": "oZLWLLamXdyG", "outputId": "4cb99132-d1e8-4770-b47a-1fc347dc4151" }, "outputs": [ { "data": { "text/markdown": [ "**Comprehensive Market Expansion Strategy for Three New Industry Verticals**\n", "\n", "**Key Findings & Recommendations:**\n", "\n", "1. **Ideal Customer Profiles & Market Fit**\n", " - **Top Industries for Expansion:**\n", " - **Technology/Software (SaaS, Fintech, Enterprise Solutions)** – Highest alignment with your current successful accounts (e.g., TechStart Inc, Global Solutions).\n", " - **Enterprise Solutions** – Strong fit for large-scale deals (e.g., Enterprise Ltd).\n", " - **Corporate/Industrial Services** – Potential in B2B industrial or supply chain solutions (e.g., Acme Corp).\n", " - **Ideal Customer Profiles:**\n", " - **Enterprise Market:** Large organizations needing scalable solutions (e.g., Robert Davis at Enterprise Ltd).\n", " - **Tech Startups:** Fast-growing companies requiring agile tools (e.g., Sarah Wilson at TechStart Inc).\n", " - **Global Services:** Consulting/outsourcing firms with cross-border needs (e.g., Michael Johnson at Global Solutions).\n", "\n", "2. **Competitive Landscape**\n", " - Limited data, but inferred competitors include:\n", " - **TechStart Inc & StartupXYZ** (direct competitors in SaaS/startup space).\n", " - **Global Solutions & Enterprise Ltd** (broader enterprise/business solutions).\n", " - **Recommendation:** Enrich data with industry classifications, revenue, and engagement metrics to refine competitive positioning.\n", "\n", "3. **Market Size & Penetration Potential**\n", " - Current dataset is too limited (only 5 companies) for accurate sizing.\n", " - **Actionable Step:** Expand data collection to include:\n", " - Industry, company size, geographic location.\n", " - Engagement metrics (emails, meetings, website activity).\n", "\n", "4. **Prioritized Market Entry Strategy**\n", " - **High-Priority Accounts (Immediate Focus):**\n", " - **Global Solutions ($125K, Lead Captured)** & **Acme Corp ($85K, Lead Nurtured)** – Assign dedicated AEs, customize proposals, and accelerate deal closure.\n", " - **Medium-Priority (TechStart Inc, $45K)** – Standardized demos + email nurturing.\n", " - **Low-Priority (StartupXYZ, $25K)** – Automated nurturing until engagement increases.\n", " - **Timeline:**\n", " - **Discovery/Qualification:** 1–2 weeks.\n", " - **Proposal/Demo:** 1–2 weeks.\n", " - **Negotiation/Close:** 1–3 weeks.\n", " - **Onboarding:** 2–4 weeks.\n", "\n", "5. **Resource Allocation**\n", " - **Sales:** Dedicate AEs to high-value accounts; automate nurturing for low-priority leads.\n", " - **Marketing:** Targeted campaigns for medium-priority accounts (e.g., case studies, retargeting ads).\n", "\n", "**Next Steps:**\n", "1. **Enrich Data:** Add industry, revenue, and engagement metrics to refine targeting.\n", "2. **Launch Pilot Campaigns:** Test strategies with high-priority accounts (Global Solutions, Acme Corp).\n", "3. **Monitor Metrics:** Track conversion rates, time-to-close, and customer satisfaction.\n", "\n", "**Conclusion:**\n", "Focus on **technology/enterprise solutions** first, prioritize high-value accounts, and scale based on engagement data. With refined data and targeted execution, you can efficiently penetrate these markets.\n", "\n", "Would you like to dive deeper into any specific area (e.g., competitive analysis, customer success tactics)?" ], "text/plain": [ "<IPython.core.display.Markdown object>" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from IPython.display import display, Markdown, Latex\n", "display(Markdown(result['final_answer']))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "prx4td0jI6wx" }, "outputs": [], "source": [] } ], "metadata": { "colab": { "provenance": [] }, "kernelspec": { "display_name": "Python 3", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 0 }