chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/dotnet run
|
||||
|
||||
#:package Microsoft.Extensions.AI@10.*
|
||||
#:package Microsoft.Agents.AI.OpenAI@1.*-*
|
||||
#:package Azure.AI.OpenAI@2.1.0
|
||||
#:package Azure.Identity@1.13.1
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
|
||||
// Tool Function: Random Destination Generator
|
||||
// This static method will be available to the agent as a callable tool
|
||||
// The [Description] attribute helps the AI understand when to use this function
|
||||
// This demonstrates how to create custom tools for AI agents
|
||||
[Description("Provides a random vacation destination.")]
|
||||
static string GetRandomDestination()
|
||||
{
|
||||
// List of popular vacation destinations around the world
|
||||
// The agent will randomly select from these options
|
||||
var destinations = new List<string>
|
||||
{
|
||||
"Paris, France",
|
||||
"Tokyo, Japan",
|
||||
"New York City, USA",
|
||||
"Sydney, Australia",
|
||||
"Rome, Italy",
|
||||
"Barcelona, Spain",
|
||||
"Cape Town, South Africa",
|
||||
"Rio de Janeiro, Brazil",
|
||||
"Bangkok, Thailand",
|
||||
"Vancouver, Canada"
|
||||
};
|
||||
|
||||
// Generate random index and return selected destination
|
||||
// Uses System.Random for simple random selection
|
||||
var random = new Random();
|
||||
int index = random.Next(destinations.Count);
|
||||
return destinations[index];
|
||||
}
|
||||
|
||||
// Azure OpenAI with the Responses API (stable v1 endpoint). Sign in with `az login`.
|
||||
var azureEndpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
|
||||
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deployment = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT") ?? "gpt-4o-mini";
|
||||
|
||||
var azureClient = new AzureOpenAIClient(new Uri(azureEndpoint), new AzureCliCredential());
|
||||
|
||||
// Define Agent Identity and Comprehensive Instructions
|
||||
// Agent name for identification and logging purposes
|
||||
var AGENT_NAME = "TravelAgent";
|
||||
|
||||
// Detailed instructions that define the agent's personality, capabilities, and behavior
|
||||
// This system prompt shapes how the agent responds and interacts with users
|
||||
var AGENT_INSTRUCTIONS = """
|
||||
You are a helpful AI Agent that can help plan vacations for customers.
|
||||
|
||||
Important: When users specify a destination, always plan for that location. Only suggest random destinations when the user hasn't specified a preference.
|
||||
|
||||
When the conversation begins, introduce yourself with this message:
|
||||
"Hello! I'm your TravelAgent assistant. I can help plan vacations and suggest interesting destinations for you. Here are some things you can ask me:
|
||||
1. Plan a day trip to a specific location
|
||||
2. Suggest a random vacation destination
|
||||
3. Find destinations with specific features (beaches, mountains, historical sites, etc.)
|
||||
4. Plan an alternative trip if you don't like my first suggestion
|
||||
|
||||
What kind of trip would you like me to help you plan today?"
|
||||
|
||||
Always prioritize user preferences. If they mention a specific destination like "Bali" or "Paris," focus your planning on that location rather than suggesting alternatives.
|
||||
""";
|
||||
|
||||
// Create AI Agent with Advanced Travel Planning Capabilities
|
||||
// Initialize complete agent pipeline: OpenAI client → Chat client → AI agent
|
||||
// Configure agent with name, detailed instructions, and available tools
|
||||
// This demonstrates the .NET agent creation pattern with full configuration
|
||||
AIAgent agent = azureClient
|
||||
.GetOpenAIResponseClient(deployment)
|
||||
.CreateAIAgent(
|
||||
name: AGENT_NAME,
|
||||
instructions: AGENT_INSTRUCTIONS,
|
||||
tools: [AIFunctionFactory.Create(GetRandomDestination)]
|
||||
);
|
||||
|
||||
// Create New Session for Context Management.
|
||||
// Initialize a new conversation session to maintain context across multiple interactions
|
||||
// Sessions enable the agent to remember previous exchanges and maintain conversational state
|
||||
// This is essential for multi-turn conversations and contextual understanding
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
|
||||
// Execute Agent: First Travel Planning Request
|
||||
// Run the agent with an initial request that will likely trigger the random destination tool
|
||||
// The agent will analyze the request, use the GetRandomDestination tool, and create an itinerary
|
||||
// Using the session parameter maintains conversation context for subsequent interactions
|
||||
await foreach (var update in agent.RunStreamingAsync("Plan me a day trip", session))
|
||||
{
|
||||
await Task.Delay(10);
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
|
||||
// Execute Agent: Follow-up Request with Context Awareness
|
||||
// Demonstrate contextual conversation by referencing the previous response
|
||||
// The agent remembers the previous destination suggestion and will provide an alternative
|
||||
// This showcases the power of conversation sessions and contextual understanding in .NET agents
|
||||
await foreach (var update in agent.RunStreamingAsync("I don't like that destination. Plan me another vacation.", session))
|
||||
{
|
||||
await Task.Delay(10);
|
||||
Console.Write(update);
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
# 🔍 Exploring Microsoft Agent Framework - Basic Agent (.NET)
|
||||
|
||||
## 📋 Learning Objectives
|
||||
|
||||
This example explores the fundamental concepts of the Microsoft Agent Framework through a basic agent implementation in .NET. You'll learn core agentic patterns and understand how intelligent agents work under the hood using C# and the .NET ecosystem.
|
||||
|
||||
### What You'll Discover
|
||||
|
||||
- 🏗️ **Agent Architecture**: Understanding the basic structure of AI agents in .NET
|
||||
- 🛠️ **Tool Integration**: How agents use external functions to extend capabilities
|
||||
- 💬 **Conversation Flow**: Managing multi-turn conversations and context with thread management
|
||||
- 🔧 **Configuration Patterns**: Best practices for agent setup and management in .NET
|
||||
|
||||
## 🎯 Key Concepts Covered
|
||||
|
||||
### Agentic Framework Principles
|
||||
|
||||
- **Autonomy**: How agents make independent decisions using .NET AI abstractions
|
||||
- **Reactivity**: Responding to environmental changes and user inputs
|
||||
- **Proactivity**: Taking initiative based on goals and context
|
||||
- **Social Ability**: Interacting through natural language with conversation threads
|
||||
|
||||
### Technical Components
|
||||
|
||||
- **AIAgent**: Core agent orchestration and conversation management (.NET)
|
||||
- **Tool Functions**: Extending agent capabilities with C# methods and attributes
|
||||
- **Azure OpenAI Integration**: Leveraging language models through the Azure OpenAI Responses API
|
||||
- **Secure Configuration**: Environment-based endpoint management
|
||||
|
||||
## 🔧 Technical Stack
|
||||
|
||||
### Core Technologies
|
||||
|
||||
- Microsoft Agent Framework (.NET)
|
||||
- Azure OpenAI (Responses API) integration
|
||||
- Azure.AI.OpenAI client patterns
|
||||
- Environment-based configuration with DotNetEnv
|
||||
|
||||
### Agent Capabilities
|
||||
|
||||
- Natural language understanding and generation
|
||||
- Function calling and tool usage with C# attributes
|
||||
- Context-aware responses with conversation threads
|
||||
- Extensible architecture with dependency injection patterns
|
||||
|
||||
## 📚 Framework Comparison
|
||||
|
||||
This example demonstrates the Microsoft Agent Framework approach compared to other agentic frameworks:
|
||||
|
||||
| Feature | Microsoft Agent Framework | Other Frameworks |
|
||||
|---------|-------------------------|------------------|
|
||||
| **Integration** | Native Microsoft ecosystem | Varied compatibility |
|
||||
| **Simplicity** | Clean, intuitive API | Often complex setup |
|
||||
| **Extensibility** | Easy tool integration | Framework-dependent |
|
||||
| **Enterprise Ready** | Built for production | Varies by framework |
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) or higher
|
||||
- An [Azure subscription](https://azure.microsoft.com/free/) with an Azure OpenAI resource and a model deployment
|
||||
- The [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) — sign in with `az login`
|
||||
|
||||
### Required Environment Variables
|
||||
|
||||
```bash
|
||||
# zsh/bash
|
||||
export AZURE_OPENAI_ENDPOINT=https://<your-resource>.openai.azure.com
|
||||
export AZURE_OPENAI_DEPLOYMENT=gpt-4o-mini
|
||||
# Then sign in so AzureCliCredential can get a token
|
||||
az login
|
||||
```
|
||||
|
||||
```powershell
|
||||
# PowerShell
|
||||
$env:AZURE_OPENAI_ENDPOINT = "https://<your-resource>.openai.azure.com"
|
||||
$env:AZURE_OPENAI_DEPLOYMENT = "gpt-4o-mini"
|
||||
# Then sign in so AzureCliCredential can get a token
|
||||
az login
|
||||
```
|
||||
|
||||
### Sample Code
|
||||
|
||||
To run the code example,
|
||||
|
||||
```bash
|
||||
# zsh/bash
|
||||
chmod +x ./02-dotnet-agent-framework.cs
|
||||
./02-dotnet-agent-framework.cs
|
||||
```
|
||||
|
||||
Or using the dotnet CLI:
|
||||
|
||||
```bash
|
||||
dotnet run ./02-dotnet-agent-framework.cs
|
||||
```
|
||||
|
||||
See [`02-dotnet-agent-framework.cs`](./02-dotnet-agent-framework.cs) for the complete code.
|
||||
|
||||
```csharp
|
||||
#!/usr/bin/dotnet run
|
||||
|
||||
#:package Microsoft.Extensions.AI@10.*
|
||||
#:package Microsoft.Agents.AI.OpenAI@1.*-*
|
||||
#:package Azure.AI.OpenAI@2.1.0
|
||||
#:package Azure.Identity@1.13.1
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
|
||||
// Tool Function: Random Destination Generator
|
||||
// This static method will be available to the agent as a callable tool
|
||||
// The [Description] attribute helps the AI understand when to use this function
|
||||
// This demonstrates how to create custom tools for AI agents
|
||||
[Description("Provides a random vacation destination.")]
|
||||
static string GetRandomDestination()
|
||||
{
|
||||
// List of popular vacation destinations around the world
|
||||
// The agent will randomly select from these options
|
||||
var destinations = new List<string>
|
||||
{
|
||||
"Paris, France",
|
||||
"Tokyo, Japan",
|
||||
"New York City, USA",
|
||||
"Sydney, Australia",
|
||||
"Rome, Italy",
|
||||
"Barcelona, Spain",
|
||||
"Cape Town, South Africa",
|
||||
"Rio de Janeiro, Brazil",
|
||||
"Bangkok, Thailand",
|
||||
"Vancouver, Canada"
|
||||
};
|
||||
|
||||
// Generate random index and return selected destination
|
||||
// Uses System.Random for simple random selection
|
||||
var random = new Random();
|
||||
int index = random.Next(destinations.Count);
|
||||
return destinations[index];
|
||||
}
|
||||
|
||||
// Azure OpenAI with the Responses API (stable v1 endpoint). Sign in with `az login`.
|
||||
var azureEndpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
|
||||
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deployment = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT") ?? "gpt-4o-mini";
|
||||
|
||||
var azureClient = new AzureOpenAIClient(new Uri(azureEndpoint), new AzureCliCredential());
|
||||
|
||||
// Define Agent Identity and Comprehensive Instructions
|
||||
// Agent name for identification and logging purposes
|
||||
var AGENT_NAME = "TravelAgent";
|
||||
|
||||
// Detailed instructions that define the agent's personality, capabilities, and behavior
|
||||
// This system prompt shapes how the agent responds and interacts with users
|
||||
var AGENT_INSTRUCTIONS = """
|
||||
You are a helpful AI Agent that can help plan vacations for customers.
|
||||
|
||||
Important: When users specify a destination, always plan for that location. Only suggest random destinations when the user hasn't specified a preference.
|
||||
|
||||
When the conversation begins, introduce yourself with this message:
|
||||
"Hello! I'm your TravelAgent assistant. I can help plan vacations and suggest interesting destinations for you. Here are some things you can ask me:
|
||||
1. Plan a day trip to a specific location
|
||||
2. Suggest a random vacation destination
|
||||
3. Find destinations with specific features (beaches, mountains, historical sites, etc.)
|
||||
4. Plan an alternative trip if you don't like my first suggestion
|
||||
|
||||
What kind of trip would you like me to help you plan today?"
|
||||
|
||||
Always prioritize user preferences. If they mention a specific destination like "Bali" or "Paris," focus your planning on that location rather than suggesting alternatives.
|
||||
""";
|
||||
|
||||
// Create AI Agent with Advanced Travel Planning Capabilities
|
||||
// Get the Responses client for the deployment and create the AI agent
|
||||
// Configure agent with name, detailed instructions, and available tools
|
||||
// This demonstrates the .NET agent creation pattern with full configuration
|
||||
AIAgent agent = azureClient
|
||||
.GetOpenAIResponseClient(deployment)
|
||||
.CreateAIAgent(
|
||||
name: AGENT_NAME,
|
||||
instructions: AGENT_INSTRUCTIONS,
|
||||
tools: [AIFunctionFactory.Create(GetRandomDestination)]
|
||||
);
|
||||
|
||||
// Create New Conversation Thread for Context Management
|
||||
// Initialize a new conversation thread to maintain context across multiple interactions
|
||||
// Threads enable the agent to remember previous exchanges and maintain conversational state
|
||||
// This is essential for multi-turn conversations and contextual understanding
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
|
||||
// Execute Agent: First Travel Planning Request
|
||||
// Run the agent with an initial request that will likely trigger the random destination tool
|
||||
// The agent will analyze the request, use the GetRandomDestination tool, and create an itinerary
|
||||
// Using the thread parameter maintains conversation context for subsequent interactions
|
||||
await foreach (var update in agent.RunStreamingAsync("Plan me a day trip", thread))
|
||||
{
|
||||
await Task.Delay(10);
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
|
||||
// Execute Agent: Follow-up Request with Context Awareness
|
||||
// Demonstrate contextual conversation by referencing the previous response
|
||||
// The agent remembers the previous destination suggestion and will provide an alternative
|
||||
// This showcases the power of conversation threads and contextual understanding in .NET agents
|
||||
await foreach (var update in agent.RunStreamingAsync("I don't like that destination. Plan me another vacation.", thread))
|
||||
{
|
||||
await Task.Delay(10);
|
||||
Console.Write(update);
|
||||
}
|
||||
```
|
||||
|
||||
## 🎓 Key Takeaways
|
||||
|
||||
1. **Agent Architecture**: The Microsoft Agent Framework provides a clean, type-safe approach to building AI agents in .NET
|
||||
2. **Tool Integration**: Functions decorated with `[Description]` attributes become available tools for the agent
|
||||
3. **Conversation Context**: Thread management enables multi-turn conversations with full context awareness
|
||||
4. **Configuration Management**: Environment variables and secure credential handling follow .NET best practices
|
||||
5. **Azure OpenAI Responses API**: The agent uses the Azure OpenAI Responses API through the Azure.AI.OpenAI SDK
|
||||
|
||||
## 🔗 Additional Resources
|
||||
|
||||
- [Microsoft Agent Framework Documentation](https://learn.microsoft.com/agent-framework)
|
||||
- [Azure OpenAI in Microsoft Foundry](https://learn.microsoft.com/azure/ai-services/openai/)
|
||||
- [Microsoft.Extensions.AI](https://learn.microsoft.com/dotnet/ai/microsoft-extensions-ai)
|
||||
- [.NET Single File Apps](https://devblogs.microsoft.com/dotnet/announcing-dotnet-run-app)
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Microsoft Agent Framework — Azure OpenAI (Responses API)\n",
|
||||
"\n",
|
||||
"In this code sample, you will use the **Microsoft Agent Framework (MAF)** to create a simple agent backed by **Azure OpenAI** using the **Responses API**.\n",
|
||||
"\n",
|
||||
"> **Migration note:** This sample previously used Semantic Kernel with GitHub Models. It has been migrated to the Microsoft Agent Framework, and GitHub Models (deprecated, retiring July 2026) has been replaced with Azure OpenAI, which supports the Responses API. The `OpenAIChatClient` in MAF targets Azure OpenAI's stable `/openai/v1/` endpoint and uses the Responses API by default.\n",
|
||||
"\n",
|
||||
"The purpose of this sample is to demonstrate the steps that will later be applied in additional code samples when implementing various agentic patterns.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%pip install agent-framework agent-framework-openai azure-identity -q\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Import the Needed Python Packages\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"import random\n",
|
||||
"\n",
|
||||
"from dotenv import load_dotenv\n",
|
||||
"from IPython.display import display, HTML\n",
|
||||
"\n",
|
||||
"from agent_framework import tool\n",
|
||||
"from agent_framework.openai import OpenAIChatClient\n",
|
||||
"from azure.identity import AzureCliCredential\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Defining a Tool\n",
|
||||
"\n",
|
||||
"In the Microsoft Agent Framework, a **tool** is a plain Python function decorated with `@tool` that the agent can call. Below we define a tool that returns a random vacation destination and avoids repeating the previous one.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# A list of vacation destinations the tool can choose from.\n",
|
||||
"_DESTINATIONS = [\n",
|
||||
" \"Barcelona, Spain\",\n",
|
||||
" \"Paris, France\",\n",
|
||||
" \"Berlin, Germany\",\n",
|
||||
" \"Tokyo, Japan\",\n",
|
||||
" \"Sydney, Australia\",\n",
|
||||
" \"New York, USA\",\n",
|
||||
" \"Cairo, Egypt\",\n",
|
||||
" \"Cape Town, South Africa\",\n",
|
||||
" \"Rio de Janeiro, Brazil\",\n",
|
||||
" \"Bali, Indonesia\",\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Track the last destination so repeated calls avoid immediate repeats.\n",
|
||||
"_last_destination: str | None = None\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"@tool(approval_mode=\"never_require\")\n",
|
||||
"def get_random_destination() -> str:\n",
|
||||
" \"\"\"Provides a random vacation destination.\"\"\"\n",
|
||||
" global _last_destination\n",
|
||||
" available = _DESTINATIONS.copy()\n",
|
||||
" if _last_destination and len(available) > 1:\n",
|
||||
" available.remove(_last_destination)\n",
|
||||
" destination = random.choice(available)\n",
|
||||
" _last_destination = destination\n",
|
||||
" return destination\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"load_dotenv()\n",
|
||||
"\n",
|
||||
"endpoint = os.environ[\"AZURE_OPENAI_ENDPOINT\"]\n",
|
||||
"deployment = os.environ.get(\"AZURE_OPENAI_DEPLOYMENT\", \"gpt-4o-mini\")\n",
|
||||
"\n",
|
||||
"# OpenAIChatClient targets Azure OpenAI's v1 endpoint and uses the Responses API.\n",
|
||||
"# Sign in with `az login` first so AzureCliCredential can authenticate.\n",
|
||||
"chat_client = OpenAIChatClient(\n",
|
||||
" model=deployment,\n",
|
||||
" azure_endpoint=endpoint,\n",
|
||||
" credential=AzureCliCredential(),\n",
|
||||
")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Creating the Agent\n",
|
||||
"\n",
|
||||
"Here, we create the Agent named `TravelAgent`.\n",
|
||||
"\n",
|
||||
"In this example, we use very basic instructions. Feel free to modify these instructions to observe how the agent's behavior changes.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"agent = chat_client.as_agent(\n",
|
||||
" name=\"TravelAgent\",\n",
|
||||
" instructions=\"You are a helpful AI Agent that can help plan vacations for customers at random destinations\",\n",
|
||||
" tools=[get_random_destination],\n",
|
||||
")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Running the Agent\n",
|
||||
"\n",
|
||||
"Now we can run the agent. We create an `AgentSession` so the agent remembers the conversation across turns, then send two `user_inputs`. The first asks for a trip; the second says the user didn't like the suggestion and asks for another — the agent uses the session history plus the `get_random_destination` tool to respond.\n",
|
||||
"\n",
|
||||
"You can modify these messages to observe how the agent reacts differently. Responses are **streamed** token-by-token.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"user_inputs = [\n",
|
||||
" \"Plan me a day trip.\",\n",
|
||||
" \"I don't like that destination. Plan me another vacation.\",\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"async def main():\n",
|
||||
" # A session keeps conversation history across turns.\n",
|
||||
" session = agent.create_session()\n",
|
||||
"\n",
|
||||
" for user_input in user_inputs:\n",
|
||||
" html_output = (\n",
|
||||
" f\"<div style='margin-bottom:10px'>\"\n",
|
||||
" f\"<div style='font-weight:bold'>User:</div>\"\n",
|
||||
" f\"<div style='margin-left:20px'>{user_input}</div></div>\"\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" full_response: list[str] = []\n",
|
||||
" # Stream the agent's response token-by-token. The agent will call the\n",
|
||||
" # get_random_destination tool automatically when it needs a destination.\n",
|
||||
" async for chunk in agent.run(user_input, session=session, stream=True):\n",
|
||||
" full_response.append(str(chunk))\n",
|
||||
"\n",
|
||||
" html_output += (\n",
|
||||
" \"<div style='margin-bottom:20px'>\"\n",
|
||||
" f\"<div style='font-weight:bold'>TravelAgent:</div>\"\n",
|
||||
" f\"<div style='margin-left:20px; white-space:pre-wrap'>{''.join(full_response)}</div></div><hr>\"\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
" display(HTML(html_output))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"await main()\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.13"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "a1b2c3d4",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Lesson 02 - Exploring Microsoft Agent Framework\n",
|
||||
"\n",
|
||||
"The **Microsoft Agent Framework (MAF)** is a unified framework for building AI agents. It provides a clean, composable architecture with four core building blocks:\n",
|
||||
"\n",
|
||||
"- **Client** – connects to an AI model endpoint and handles communication\n",
|
||||
"- **Agent** – wraps a client with instructions and tool definitions\n",
|
||||
"- **Tools** – extend agent capabilities with custom functions the model can call\n",
|
||||
"- **Session** – maintains conversation history for multi-turn interactions\n",
|
||||
"\n",
|
||||
"In this lesson, we'll build a **travel booking agent** that checks destination availability using these concepts."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "b2c3d4e5",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Setup"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "c3d4e5f6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Install the Microsoft Agent Framework package\n",
|
||||
"! pip install agent-framework azure-ai-projects -U -q\n",
|
||||
"! pip install python-dotenv -q"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "d4e5f6a7",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import logging\n",
|
||||
"logging.getLogger(\"agent_framework.foundry\").setLevel(logging.ERROR)\n",
|
||||
"\n",
|
||||
"import os\n",
|
||||
"import asyncio\n",
|
||||
"import dotenv\n",
|
||||
"from typing import Annotated\n",
|
||||
"\n",
|
||||
"from agent_framework import tool\n",
|
||||
"from agent_framework.foundry import FoundryChatClient\n",
|
||||
"from azure.identity import AzureCliCredential\n",
|
||||
"\n",
|
||||
"dotenv.load_dotenv(dotenv.find_dotenv())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "e5f6a7b8",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Understanding the Agent Framework Architecture\n",
|
||||
"\n",
|
||||
"The Microsoft Agent Framework follows a layered architecture:\n",
|
||||
"\n",
|
||||
"```\n",
|
||||
"Client → Agent → Tools\n",
|
||||
" → Session\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"1. **Client** – A `FoundryChatClient` connects to an Azure OpenAI deployment. It handles authentication, request formatting, and response parsing.\n",
|
||||
"2. **Agent** – Created from the client via `provider.create_agent()`, the agent combines model access with instructions (system prompt) and tools.\n",
|
||||
"3. **Tools** – Python functions decorated with `@tool` that the agent can invoke to perform actions or retrieve data.\n",
|
||||
"4. **Session** – An `AgentSession` object (created via `agent.create_session()`) that stores conversation history, enabling multi-turn dialogue where the agent remembers prior context.\n",
|
||||
"\n",
|
||||
"Let's build each layer step by step."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "f6a7b8c9",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Create the client – this is the connection to the AI model\n",
|
||||
"endpoint = os.getenv(\"AZURE_AI_PROJECT_ENDPOINT\")\n",
|
||||
"model = os.getenv(\"AZURE_AI_MODEL_DEPLOYMENT_NAME\")\n",
|
||||
"\n",
|
||||
"if not endpoint or not model:\n",
|
||||
" raise ValueError(\n",
|
||||
" \"Missing required environment variables. \"\n",
|
||||
" \"Please set AZURE_AI_PROJECT_ENDPOINT and AZURE_AI_MODEL_DEPLOYMENT_NAME as environment variables (e.g., in your .env file or shell environment).\"\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"provider = FoundryChatClient(\n",
|
||||
" project_endpoint=endpoint,\n",
|
||||
" model=model,\n",
|
||||
" credential=AzureCliCredential()\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "a7b8c9d0",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Adding Tools with the @tool Decorator\n",
|
||||
"\n",
|
||||
"Tools let agents take actions beyond generating text. The `@tool` decorator converts a regular Python function into something the agent can call.\n",
|
||||
"\n",
|
||||
"Key points:\n",
|
||||
"- Use `Annotated[type, \"description\"]` so the model understands each parameter.\n",
|
||||
"- The docstring becomes the tool description the model sees.\n",
|
||||
"- `approval_mode=\"never_require\"` means the tool runs automatically without user confirmation."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "b8c9d0e1",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"@tool(approval_mode=\"never_require\")\n",
|
||||
"def check_destination_availability(\n",
|
||||
" destination: Annotated[str, \"The destination to check availability for\"]\n",
|
||||
") -> str:\n",
|
||||
" \"\"\"Check if a vacation destination is currently available for booking.\"\"\"\n",
|
||||
" available = {\n",
|
||||
" \"Barcelona\": True,\n",
|
||||
" \"Tokyo\": True,\n",
|
||||
" \"Cape Town\": False,\n",
|
||||
" \"Vancouver\": True,\n",
|
||||
" \"Dubai\": False,\n",
|
||||
" }\n",
|
||||
" is_available = available.get(destination, False)\n",
|
||||
" return f\"{destination} is {'available' if is_available else 'not available'} for booking.\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "c9d0e1f2",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Creating an Agent with Tools\n",
|
||||
"\n",
|
||||
"Now we combine the client, instructions, and tools into an agent. The `instructions` act as the system prompt — they define the agent's persona and behaviour."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "d0e1f2a3",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"agent = provider.as_agent(\n",
|
||||
" name=\"TravelAvailabilityAgent\",\n",
|
||||
" instructions=(\n",
|
||||
" \"You are a travel booking agent. Help users check destination availability \"\n",
|
||||
" \"and make recommendations. Always check availability before recommending a destination.\"\n",
|
||||
" ),\n",
|
||||
" tools=[check_destination_availability],\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "e1f2a3b4",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Multi-Turn Conversations with Sessions\n",
|
||||
"\n",
|
||||
"An `AgentSession` (created via `agent.create_session()`) keeps track of all messages in a conversation. By passing the same session to each `agent.run()` call, the agent has access to the full conversation history and can refer back to earlier messages.\n",
|
||||
"\n",
|
||||
"We pass `tools=[check_destination_availability]` so the agent can call our availability checker during each turn."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "f2a3b4c5",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"session = agent.create_session()\n",
|
||||
"\n",
|
||||
"# Turn 1: Ask about available destinations\n",
|
||||
"response = await agent.run(\n",
|
||||
" \"Which destinations do you have available?\",\n",
|
||||
" session=session,\n",
|
||||
")\n",
|
||||
"print(f\"Agent: {response}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "a3b4c5d6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Turn 2: Follow-up question — the agent remembers the conversation\n",
|
||||
"response = await agent.run(\n",
|
||||
" \"I'd like to go somewhere warm. What's available?\",\n",
|
||||
" session=session,\n",
|
||||
")\n",
|
||||
"print(f\"Agent: {response}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "b4c5d6e7",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Summary\n",
|
||||
"\n",
|
||||
"In this lesson you explored the four pillars of the Microsoft Agent Framework:\n",
|
||||
"\n",
|
||||
"| Concept | What You Learned |\n",
|
||||
"|---------|------------------|\n",
|
||||
"| **Client** | `FoundryChatClient` connects to Azure OpenAI with credential-based auth |\n",
|
||||
"| **Agent** | `provider.create_agent()` bundles a model connection with instructions and a name |\n",
|
||||
"| **Tools** | The `@tool` decorator exposes Python functions for the agent to call |\n",
|
||||
"| **Session** | `agent.create_session()` maintains conversation history across multiple turns |\n",
|
||||
"\n",
|
||||
"These building blocks compose together to create agents that can hold natural conversations, call external functions, and maintain context — the foundation for more advanced agentic patterns in later lessons."
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
Reference in New Issue
Block a user