{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "4b2cf5f5", "metadata": {}, "outputs": [], "source": [ "import asyncio\n", "import json\n", "import os\n", "from typing import Annotated, Any, Never\n", "\n", "from agent_framework import (\n", " AgentExecutor,\n", " AgentExecutorRequest,\n", " AgentExecutorResponse,\n", " Message,\n", " WorkflowBuilder,\n", " WorkflowContext,\n", " executor,\n", " tool,\n", ")\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": "001c224e", "metadata": {}, "source": [ "## Step 1: Define Pydantic Models for Structured Outputs\n", "\n", "These models define the **schema** that agents will return. Using `response_format` with Pydantic ensures:\n", "- ✅ Type-safe data extraction\n", "- ✅ Automatic validation\n", "- ✅ No parsing errors from free-text responses\n", "- ✅ Easy conditional routing based on fields" ] }, { "cell_type": "code", "execution_count": null, "id": "6c2ef582", "metadata": {}, "outputs": [], "source": [ "class BookingCheckResult(BaseModel):\n", " \"\"\"Result from checking hotel availability at a destination.\"\"\"\n", "\n", " destination: str\n", " has_availability: bool\n", " message: str\n", "\n", "\n", "class AlternativeResult(BaseModel):\n", " \"\"\"Suggested alternative destination when no rooms available.\"\"\"\n", "\n", " alternative_destination: str\n", " reason: str\n", "\n", "\n", "class BookingConfirmation(BaseModel):\n", " \"\"\"Booking suggestion when rooms are available.\"\"\"\n", "\n", " destination: str\n", " action: str\n", " message: str\n", "\n", "\n", "print(\"✅ Pydantic models defined:\")\n", "print(\" - BookingCheckResult (availability check)\")\n", "print(\" - AlternativeResult (alternative suggestion)\")\n", "print(\" - BookingConfirmation (booking confirmation)\")" ] }, { "cell_type": "markdown", "id": "48423ecc", "metadata": {}, "source": [ "## Step 2: Create the Hotel Booking Tool\n", "\n", "This tool is what the **availability_agent** will call to check if rooms are available. We use the `@ai_function` decorator to:\n", "- Convert a Python function into an AI-callable tool\n", "- Automatically generate JSON schema for the LLM\n", "- Handle parameter validation\n", "- Enable automatic invocation by agents\n", "\n", "For this demo:\n", "- **Stockholm, Seattle, Tokyo, London, Amsterdam** → Have rooms ✅\n", "- **All other cities** → No rooms ❌" ] }, { "cell_type": "code", "execution_count": null, "id": "aad7e7ec", "metadata": {}, "outputs": [], "source": [ "@tool(description=\"Check hotel room availability for a destination city\")\n", "def hotel_booking(destination: Annotated[str, \"The destination city to check for hotel rooms\"]) -> str:\n", " \"\"\"\n", " Simulates checking hotel room availability.\n", "\n", " Returns JSON string with availability status.\n", " \"\"\"\n", " display(\n", " HTML(f\"\"\"\n", "
\n",
" Conditional Routing:
\n",
" • If NO availability → alternative_agent → display_result
\n",
" • If availability → booking_agent → display_result\n",
"
Expected workflow path: availability_agent → alternative_agent → display_result
\n", "Status: ❌ No rooms in Paris
\n", "Alternative Suggestion: 🏨 {result_paris.alternative_destination}
\n", "Reason: {result_paris.reason}
\n", "Expected workflow path: availability_agent → booking_agent → display_result
\n", "Status: ✅ Rooms Available!
\n", "Destination: 🏨 {result_stockholm.destination}
\n", "Action: {result_stockholm.action}
\n", "Message: {result_stockholm.message}
\n", "