{ "cells": [ { "cell_type": "markdown", "id": "2b91961c", "metadata": {}, "source": [ "## Two Sequential Agents:\n", "\n", "1. **Front Desk Agent**: Makes initial attraction recommendations for the city\n", "2. **Concierge Agent**: Reviews and rates the front desk recommendation based on popularity\n", "\n", "## Key Benefits of Sequential Orchestration:\n", "\n", "- **Iterative Refinement**: Second agent improves upon first agent's work\n", "- **Specialization**: Each agent has a specific role in the process\n", "- **Quality Control**: Built-in review and validation step\n", "- **Clear Information Flow**: Structured handoff between agents\n", "\n", "## Prerequisites:\n", "- Microsoft Agent Framework installed\n", "- Microsoft Foundry project endpoint and model deployment configured (`AZURE_AI_PROJECT_ENDPOINT`, `AZURE_AI_MODEL_DEPLOYMENT_NAME`)\n", "- Authenticated via Azure CLI (`az login`)\n", "- Understanding of basic agent concepts\n" ] }, { "cell_type": "code", "execution_count": null, "id": "0981c0bb", "metadata": {}, "outputs": [], "source": [ "import asyncio\n", "import json\n", "import os\n", "from typing import Any, cast\n", "\n", "from agent_framework import Message, WorkflowBuilder\n", "from agent_framework.foundry import FoundryChatClient\n", "from azure.identity import AzureCliCredential\n", "from dotenv import load_dotenv\n", "from IPython.display import HTML, display\n", "from pydantic import BaseModel\n", "\n", "print(\"All imports successful!\")\n" ] }, { "cell_type": "markdown", "id": "790b74bd", "metadata": {}, "source": [ "## Step 1: Define Pydantic Models for Structured Outputs\n", "\n", "These models define the schema that each agent will return. The front desk agent provides a recommendation, and the concierge agent provides a review and rating." ] }, { "cell_type": "code", "execution_count": null, "id": "3436dc8d", "metadata": {}, "outputs": [], "source": [ "class AttractionRecommendation(BaseModel):\n", " \"\"\"Attraction recommendation from the front desk agent.\"\"\"\n", "\n", " city: str\n", " attraction_name: str\n", " description: str\n", " category: str # e.g., \"museum\", \"landmark\", \"park\", \"entertainment\"\n", " recommended_duration: str # e.g., \"2-3 hours\", \"half day\"\n", " why_recommended: str\n", " best_time_to_visit: str\n", "\n", "\n", "class AttractionReview(BaseModel):\n", " \"\"\"Expert review and rating from the concierge agent.\"\"\"\n", "\n", " attraction_name: str\n", " city: str\n", " popularity_score: int # 1-10 scale\n", " popularity_reasoning: str\n", " visitor_rating: float # 1.0-5.0 scale\n", " pros: list[str]\n", " cons: list[str]\n", " concierge_recommendation: str\n", " alternative_suggestions: list[str]" ] }, { "cell_type": "markdown", "id": "f4269b29", "metadata": {}, "source": [ "## Step 2: Load Environment Variables and Configure the Foundry Provider\n", "\n", "Use `FoundryChatClient` with keyless `AzureCliCredential` authentication, matching the pattern used in lessons 01–13.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "2152c7d3", "metadata": {}, "outputs": [], "source": [ "# Load environment variables\n", "load_dotenv()\n", "\n", "# Configure the Microsoft Foundry provider with keyless authentication\n", "provider = FoundryChatClient(\n", " project_endpoint=os.environ[\"AZURE_AI_PROJECT_ENDPOINT\"],\n", " model=os.environ[\"AZURE_AI_MODEL_DEPLOYMENT_NAME\"],\n", " credential=AzureCliCredential(),\n", ")\n", "\n", "print(\"Microsoft Foundry provider configured successfully!\")\n" ] }, { "cell_type": "markdown", "id": "e63c63dd", "metadata": {}, "source": [ "## Step 3: Create Two Sequential Agents\n", "\n", "Each agent has a specific role in the sequential workflow. The front desk agent makes recommendations, and the concierge agent reviews and rates them.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "3f862eee", "metadata": {}, "outputs": [], "source": [ "# Agent 1: Front Desk Agent (Makes initial recommendations)\n", "front_desk_agent = provider.as_agent(\n", " name=\"front-desk-agent\",\n", " instructions=(\n", " \"You are a knowledgeable hotel front desk agent who specializes in local attractions. \"\n", " \"When a guest asks about attractions in a city, provide a single, well-researched recommendation \"\n", " \"for a popular tourist attraction. Focus on giving practical information including what makes \"\n", " \"this attraction special, how long to spend there, and the best time to visit. \"\n", " \"Be helpful and enthusiastic about your recommendation. \"\n", " \"Return structured JSON matching the AttractionRecommendation schema.\"\n", " ),\n", ")\n", "\n", "# Agent 2: Concierge Agent (Reviews and rates recommendations)\n", "concierge_agent = provider.as_agent(\n", " name=\"concierge-agent\",\n", " instructions=(\n", " \"You are an expert concierge with extensive knowledge of tourist attractions worldwide. \"\n", " \"You will receive an attraction recommendation and must provide an expert review and rating. \"\n", " \"Evaluate the recommendation based on the attraction's popularity, visitor satisfaction, \"\n", " \"and overall quality. Provide a popularity score (1-10), visitor rating (1.0-5.0), \"\n", " \"list pros and cons, and give your professional assessment. \"\n", " \"Also suggest alternative attractions if appropriate. \"\n", " \"Return structured JSON matching the AttractionReview schema.\"\n", " ),\n", ")\n", "\n" ] }, { "cell_type": "markdown", "id": "0afa99f5", "metadata": {}, "source": [ "## Step 4: Build the Sequential Workflow\n", "\n", "`WorkflowBuilder` creates a workflow where:\n", "1. **Front Desk Agent** receives user input and makes a recommendation\n", "2. **Concierge Agent** receives the front desk recommendation and provides expert review\n", "3. **Output** contains both the original recommendation and the expert review" ] }, { "cell_type": "code", "execution_count": null, "id": "d76c5b11", "metadata": {}, "outputs": [], "source": [ "# Build the sequential workflow with WorkflowBuilder\n", "workflow = (\n", " WorkflowBuilder(\n", " start_executor=front_desk_agent,\n", " output_executors=[front_desk_agent, concierge_agent],\n", " )\n", " .add_edge(front_desk_agent, concierge_agent)\n", " .build()\n", ")\n", "\n", "display(HTML(\"\"\"\n", "
\n",
" Flow:
\n",
" • User Input → Front Desk Agent (recommendation)
\n",
" • Front Desk Output → Concierge Agent (review & rating)
\n",
" • Final Output → Combined recommendation + expert review\n",
"
Status: Running sequential workflow...
\n", "Generated by sequential agent workflow
\n", "Examining agent interactions and information handoff...
\n", "