From 1247eb9e6e5d0190e87e4f345453f1bb501528d7 Mon Sep 17 00:00:00 2001 From: Leo Yao Date: Fri, 27 Feb 2026 11:46:51 -0800 Subject: [PATCH 01/14] Add foundry extension samples for python and dotnet --- .../foundry_multiagent/Dockerfile | 22 ++ .../foundry_multiagent/Program.cs | 166 ++++++++++++++ .../HostedAgents/foundry_multiagent/README.md | 169 +++++++++++++++ .../foundry_multiagent/agent.yaml | 24 +++ .../appsettings.Development.json | 4 + .../dotnetmultiagent.csproj | 30 +++ .../foundry_single_agent/Dockerfile | 20 ++ .../foundry_single_agent/Program.cs | 136 ++++++++++++ .../foundry_single_agent/README.md | 166 ++++++++++++++ .../foundry_single_agent/agent.yaml | 25 +++ .../foundry_single_agent/dotnetsingle.csproj | 16 ++ .../foundry_single_agent/run-requests.http | 52 +++++ .../foundry_multiagent/Dockerfile | 15 ++ .../foundry_multiagent/README.md | 204 ++++++++++++++++++ .../foundry_multiagent/agent.yaml | 24 +++ .../hosted_agents/foundry_multiagent/main.py | 107 +++++++++ .../foundry_multiagent/requirements.txt | 4 + .../foundry_single_agent/Dockerfile | 15 ++ .../foundry_single_agent/README.md | 195 +++++++++++++++++ .../foundry_single_agent/agent.yaml | 25 +++ .../foundry_single_agent/main.py | 149 +++++++++++++ .../foundry_single_agent/requirements.txt | 4 + 22 files changed, 1572 insertions(+) create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Dockerfile create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Program.cs create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/README.md create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/agent.yaml create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/appsettings.Development.json create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/dotnetmultiagent.csproj create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Dockerfile create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Program.cs create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/README.md create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/agent.yaml create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/dotnetsingle.csproj create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/run-requests.http create mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_multiagent/Dockerfile create mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md create mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml create mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py create mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt create mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_single_agent/Dockerfile create mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md create mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml create mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py create mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Dockerfile b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Dockerfile new file mode 100644 index 0000000000..b4d16d949e --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Dockerfile @@ -0,0 +1,22 @@ +# Build the application +FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build +WORKDIR /src + +# Copy project files for dependency resolution +COPY *.csproj* . +RUN dotnet restore dotnetmultiagent.csproj + +# Copy files from the current directory on the host to the working directory in the container +COPY . . + +RUN dotnet publish -c Release -o /app -p:AssemblyName=app + +# Run the application +FROM mcr.microsoft.com/dotnet/aspnet:9.0 +WORKDIR /app + +# Copy everything needed to run the app from the "build" stage. +COPY --from=build /app . + +EXPOSE 8088 +ENTRYPOINT ["dotnet", "app.dll"] diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Program.cs b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Program.cs new file mode 100644 index 0000000000..df66e846f9 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Program.cs @@ -0,0 +1,166 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Azure.AI.Agents.Persistent; +using Azure.AI.AgentServer.AgentFramework.Extensions; +using Azure.Core; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Workflows; +using Microsoft.Extensions.AI; +using Microsoft.Extensions.Configuration; +using OpenTelemetry; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; + +namespace dotnetmultiagent; + +internal static class Program +{ + private static TracerProvider? s_tracerProvider; + + private static async Task Main(string[] args) + { + try + { + // Enable OpenTelemetry tracing for visualization + ConfigureObservability(); + + await RunAsync().ConfigureAwait(false); + } + catch (Exception e) + { + Console.WriteLine($"Critical error: {e}"); + } + } + + private static async ValueTask RunAsync() + { + // Build configuration + var configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.Development.json", optional: true) + .AddEnvironmentVariables() + .Build(); + + var endpoint = + configuration["PROJECT_ENDPOINT"] + ?? throw new InvalidOperationException( + "PROJECT_ENDPOINT is required. Set it in appsettings.Development.json for local development or as PROJECT_ENDPOINT environment variable for production"); + var deployment = + configuration["MODEL_DEPLOYMENT_NAME"] + ?? throw new InvalidOperationException( + "MODEL_DEPLOYMENT_NAME is required. Set it in appsettings.Development.json for local development or as MODEL_DEPLOYMENT_NAME environment variable for containers"); + + Console.WriteLine($"Using Azure AI endpoint: {endpoint}"); + Console.WriteLine($"Using model deployment: {deployment}"); + + // Create credential - use ManagedIdentityCredential if MSI_ENDPOINT exists, otherwise DefaultAzureCredential + TokenCredential credential = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSI_ENDPOINT")) + ? new DefaultAzureCredential() + : new ManagedIdentityCredential(); + + // Create separate PersistentAgentsClient for each agent + var writerClient = new PersistentAgentsClient(endpoint, credential); + var reviewerClient = new PersistentAgentsClient(endpoint, credential); + + (ChatClientAgent agent, string id)? writer = null; + (ChatClientAgent agent, string id)? reviewer = null; + + try + { + // Create Foundry agents with separate clients + writer = await CreateAgentAsync( + writerClient, + deployment, + "Writer", + "You are an excellent content writer. You create new content and edit contents based on the feedback." + ); + reviewer = await CreateAgentAsync( + reviewerClient, + deployment, + "Reviewer", + "You are an excellent content reviewer. Provide actionable feedback to the writer about the provided content. Provide the feedback in the most concise manner possible." + ); + Console.WriteLine(); + + var workflow = new WorkflowBuilder(writer.Value.agent) + .AddEdge(writer.Value.agent, reviewer.Value.agent) + .WithOutputFrom(reviewer.Value.agent) + .Build(); + + Console.WriteLine("Starting Writer-Reviewer Workflow Agent Server on http://localhost:8088"); + await workflow.AsAgent().RunAIAgentAsync(); + } + catch (Exception ex) + { + Console.WriteLine($"Error running workflow: {ex.Message}"); + throw; + } + finally + { + // Clean up all resources + await CleanupAsync(writerClient, writer?.id); + await CleanupAsync(reviewerClient, reviewer?.id); + + if (credential is IDisposable disposable) + { + disposable.Dispose(); + } + } + } + + private static async Task<(ChatClientAgent agent, string id)> CreateAgentAsync( + PersistentAgentsClient client, + string model, + string name, + string instructions) + { + var agentMetadata = await client.Administration.CreateAgentAsync( + model: model, + name: name, + instructions: instructions + ); + + var chatClient = client.AsIChatClient(agentMetadata.Value.Id); + return (new ChatClientAgent(chatClient), agentMetadata.Value.Id); + } + + private static async Task CleanupAsync(PersistentAgentsClient client, string? agentId) + { + if (string.IsNullOrEmpty(agentId)) + { + return; + } + + try + { + await client.Administration.DeleteAgentAsync(agentId); + } + catch (Exception e) + { + Console.WriteLine($"Cleanup failed for agent {agentId}: {e.Message}"); + } + } + + private static void ConfigureObservability() + { + var otlpEndpoint = + Environment.GetEnvironmentVariable("OTLP_ENDPOINT") ?? "http://localhost:4319"; + + var resourceBuilder = ResourceBuilder.CreateDefault() + .AddService("WorkflowSample"); + + s_tracerProvider = Sdk.CreateTracerProviderBuilder() + .SetResourceBuilder(resourceBuilder) + .AddSource("Microsoft.Agents.AI.*") // All agent framework sources + .SetSampler(new AlwaysOnSampler()) // Ensure all traces are sampled + .AddOtlpExporter(options => + { + options.Endpoint = new Uri(otlpEndpoint); + options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc; + }) + .Build(); + + Console.WriteLine($"OpenTelemetry configured. OTLP endpoint: {otlpEndpoint}"); + } +} diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/README.md b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/README.md new file mode 100644 index 0000000000..fde0fb26b4 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/README.md @@ -0,0 +1,169 @@ +**IMPORTANT!** All samples and other resources made available in this GitHub repository ("samples") are designed to assist in accelerating development of agents, solutions, and agent workflows for various scenarios. Review all provided resources and carefully test output behavior in the context of your use case. AI responses may be inaccurate and AI actions should be monitored with human oversight. Learn more in the transparency documents for [Agent Service](https://learn.microsoft.com/en-us/azure/ai-foundry/responsible-ai/agents/transparency-note) and [Agent Framework](https://github.com/microsoft/agent-framework/blob/main/TRANSPARENCY_FAQ.md). + +Agents, solutions, or other output you create may be subject to legal and regulatory requirements, may require licenses, or may not be suitable for all industries, scenarios, or use cases. By using any sample, you are acknowledging that any output created using those samples are solely your responsibility, and that you will comply with all applicable laws, regulations, and relevant safety standards, terms of service, and codes of conduct. + +Third-party samples contained in this folder are subject to their own designated terms, and they have not been tested or verified by Microsoft or its affiliates. + +Microsoft has no responsibility to you or others with respect to any of these samples or any resulting output. + +# What this sample demonstrates + +This sample demonstrates a **key advantage of code-based hosted agents**: + +- **Multi-agent workflows** - Orchestrate multiple agents working together + +Code-based agents can execute **any C# code** you write. This sample includes a Writer-Reviewer workflow where two agents collaborate: a Writer creates content and a Reviewer provides feedback. + +The agent is hosted using the [Azure AI AgentServer SDK](https://www.nuget.org/packages/Azure.AI.AgentServer.AgentFramework/) and can be deployed to Microsoft Foundry. + +## How It Works + +### Multi-Agent Workflow + +In [Program.cs](Program.cs), the sample creates two agents using `PersistentAgentsClient`: + +- **Writer** - An agent that creates and edits content based on feedback +- **Reviewer** - An agent that provides actionable feedback on the content + +The `WorkflowBuilder` connects these agents in a sequential flow: + +1. The Writer receives the initial request and generates content +2. The Reviewer evaluates the content and provides feedback +3. Both agent responses are output to the user + +### Agent Hosting + +The agent is hosted using the [Azure AI AgentServer SDK](https://www.nuget.org/packages/Azure.AI.AgentServer.AgentFramework/), +which provisions a REST API endpoint compatible with the OpenAI Responses protocol. + +## Running the Agent Locally + +### Prerequisites + +Before running this sample, ensure you have: + +1. **Azure AI Foundry Project** + - Project created. + - Chat model deployed (e.g., `gpt-4o` or `gpt-4.1`) + - Note your project endpoint URL and model deployment name + > **Note**: You can right-click the project in the Microsoft Foundry VS Code extension and select `Copy Project Endpoint URL` to get the endpoint. + +2. **Azure CLI** + - Installed and authenticated + - Run `az login` and verify with `az account show` + +3. **.NET 10.0 SDK or later** + - Verify your version: `dotnet --version` + - Download from [https://dotnet.microsoft.com/download](https://dotnet.microsoft.com/download) + +### Environment Variables + +**Foundry VS Code Extension Users:** + +If you created your hosted agent project using the Microsoft Foundry VS Code extension, a `appsettings.Development.json` file is already created in the project root with the necessary environment variables. Double-check that the values are correct. + +**PowerShell:** + +```powershell +# Replace with your actual values +$env:PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" +$env:MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +``` + +**Bash:** + +```bash +export PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" +export MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +``` + +### Running the Sample + +To run the agent, execute the following command in your terminal: + +```bash +dotnet restore +dotnet build +dotnet run +``` + +This will start the hosted agent locally on `http://localhost:8088/`. + +### Interacting with the Agent + +**VS Code:** + +1. Open the Visual Studio Code Command Palette and execute the `Microsoft Foundry: Open Container Agent Playground Locally` command. +2. Execute the following commands to start the containerized hosted agent. + ```bash + dotnet restore + dotnet build + dotnet run + ``` +3. Submit a request to the agent through the playground interface. For example, you may enter a prompt such as: "Create a slogan for a new electric SUV that is affordable and fun to drive." +4. Review the agent's response in the playground interface. + +> **Note**: Open the local playground before starting the container agent to ensure the visualization functions correctly. + +**PowerShell (Windows):** + +```powershell +$body = @{ + input = "Create a slogan for a new electric SUV that is affordable and fun to drive" + stream = $false +} | ConvertTo-Json + +Invoke-RestMethod -Uri http://localhost:8088/responses -Method Post -Body $body -ContentType "application/json" +``` + +**Bash/curl (Linux/macOS):** + +```bash +curl -sS -H "Content-Type: application/json" -X POST http://localhost:8088/responses \ + -d '{"input": "Create a slogan for a new electric SUV that is affordable and fun to drive","stream":false}' +``` + +You can also use the `run-requests.http` file in this directory with the VS Code REST Client extension. + +The Writer agent will generate content based on your prompt, and the Reviewer agent will provide feedback on the output. + +## Deploying the Agent to Microsoft Foundry + +**Preparation (required)** + +Please check the environment_variables section in [agent.yaml](agent.yaml) and ensure the variables there are set in your target Microsoft Foundry Project. + +To deploy the hosted agent: + +1. Open the VS Code Command Palette and run the `Microsoft Foundry: Deploy Hosted Agent` command. + +2. Follow the interactive deployment prompts. The extension will help you select or create the container files it needs. + +3. After deployment completes, the hosted agent appears under the `Hosted Agents (Preview)` section of the extension tree. You can select the agent there to view details and test it using the integrated playground. + +**What the deploy flow does for you:** + +- Creates or obtains an Azure Container Registry for the target project. +- Builds and pushes a container image from your workspace (the build packages the workspace respecting `.dockerignore`). +- Creates an agent version in Microsoft Foundry using the built image. If a `.env` file exists at the workspace root, the extension will parse it and include its key/value pairs as the hosted agent's environment variables in the create request (these variables will be available to the agent runtime). +- Starts the agent container on the project's capability host. If the capability host is not provisioned, the extension will prompt you to enable it and will guide you through creating it. + +## MSI Configuration in the Azure Portal + +This sample requires the Microsoft Foundry Project to authenticate using a Managed Identity when running remotely in Azure. Grant the project's managed identity the required permissions by assigning the built-in [Azure AI User](https://aka.ms/foundry-ext-project-role) role. + +To configure the Managed Identity: + +1. In the Azure Portal, open the Foundry Project. +2. Select "Access control (IAM)" from the left-hand menu. +3. Click "Add" and choose "Add role assignment". +4. In the role selection, search for and select "Azure AI User", then click "Next". +5. For "Assign access to", choose "Managed identity". +6. Click "Select members", locate the managed identity associated with your Foundry Project (you can search by the project name), then click "Select". +7. Click "Review + assign" to complete the assignment. +8. Allow a few minutes for the role assignment to propagate before running the application. + +## Additional Resources + +- [Microsoft Agents Framework](https://learn.microsoft.com/en-us/agent-framework/overview/agent-framework-overview) +- [Managed Identities for Azure Resources](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/) diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/agent.yaml b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/agent.yaml new file mode 100644 index 0000000000..809524dc9a --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/agent.yaml @@ -0,0 +1,24 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml + +kind: hosted +name: dotnet-multiagent +description: > + A multi-agent workflow featuring a Writer and Reviewer that collaborate + to create and refine content. +metadata: + authors: + - Microsoft + tags: + - Azure AI AgentServer + - Microsoft Agent Framework + - Multi-Agent Workflow + - Writer-Reviewer + - Content Creation +protocols: + - protocol: responses + version: v1 +environment_variables: + - name: PROJECT_ENDPOINT + value: "{{PROJECT_ENDPOINT}}" + - name: MODEL_DEPLOYMENT_NAME + value: "{{MODEL_DEPLOYMENT_NAME}}" diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/appsettings.Development.json b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/appsettings.Development.json new file mode 100644 index 0000000000..270a481008 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/appsettings.Development.json @@ -0,0 +1,4 @@ +{ + "PROJECT_ENDPOINT": "https://leoyao-agent-eastus2-resource.services.ai.azure.com/api/projects/leoyao-agent-eastus2", + "MODEL_DEPLOYMENT_NAME": "gpt-5.2" +} diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/dotnetmultiagent.csproj b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/dotnetmultiagent.csproj new file mode 100644 index 0000000000..d884ae2b5e --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/dotnetmultiagent.csproj @@ -0,0 +1,30 @@ + + + Exe + net9.0 + enable + enable + + + + + + + + + + + + + + + + + + PreserveNewest + + + diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Dockerfile b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Dockerfile new file mode 100644 index 0000000000..493a4076e4 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Dockerfile @@ -0,0 +1,20 @@ +# Build the application +FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build +WORKDIR /src + +# Copy files from the current directory on the host to the working directory in the container +COPY . . + +RUN dotnet restore +RUN dotnet build -c Release --no-restore +RUN dotnet publish -c Release --no-build -o /app + +# Run the application +FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final +WORKDIR /app + +# Copy everything needed to run the app from the "build" stage. +COPY --from=build /app . + +EXPOSE 8088 +ENTRYPOINT ["dotnet", "dotnetsingle.dll"] diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Program.cs b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Program.cs new file mode 100644 index 0000000000..5b2859632d --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Program.cs @@ -0,0 +1,136 @@ +// Seattle Hotel Agent - A simple agent with a tool to find hotels in Seattle. +// Uses Microsoft Agent Framework with Azure AI Foundry. +// Ready for deployment to Foundry Hosted Agent service. + +using System.ComponentModel; +using System.Globalization; +using System.Text; +using System.ClientModel.Primitives; +using Azure.AI.AgentServer.AgentFramework.Extensions; +using Azure.AI.OpenAI; +using Azure.AI.Projects; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +// Get configuration from environment variables +var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set."); +var deploymentName = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME") ?? "gpt-4.1-mini"; +Console.WriteLine($"Project Endpoint: {endpoint}"); +Console.WriteLine($"Model Deployment: {deploymentName}"); +// Simulated hotel data for Seattle +var seattleHotels = new[] +{ + new Hotel("Contoso Suites", 189, 4.5, "Downtown"), + new Hotel("Fabrikam Residences", 159, 4.2, "Pike Place Market"), + new Hotel("Alpine Ski House", 249, 4.7, "Seattle Center"), + new Hotel("Margie's Travel Lodge", 219, 4.4, "Waterfront"), + new Hotel("Northwind Inn", 139, 4.0, "Capitol Hill"), + new Hotel("Relecloud Hotel", 99, 3.8, "University District"), +}; + +[Description("Get available hotels in Seattle for the specified dates. This simulates a call to a hotel availability API.")] +string GetAvailableHotels( + [Description("Check-in date in YYYY-MM-DD format")] string checkInDate, + [Description("Check-out date in YYYY-MM-DD format")] string checkOutDate, + [Description("Maximum price per night in USD (optional, defaults to 500)")] int maxPrice = 500) +{ + try + { + // Parse dates + if (!DateTime.TryParseExact(checkInDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var checkIn)) + { + return $"Error parsing check-in date. Please use YYYY-MM-DD format."; + } + + if (!DateTime.TryParseExact(checkOutDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var checkOut)) + { + return $"Error parsing check-out date. Please use YYYY-MM-DD format."; + } + + // Validate dates + if (checkOut <= checkIn) + { + return "Error: Check-out date must be after check-in date."; + } + + var nights = (checkOut - checkIn).Days; + + // Filter hotels by price + var availableHotels = seattleHotels.Where(h => h.PricePerNight <= maxPrice).ToList(); + + if (availableHotels.Count == 0) + { + return $"No hotels found in Seattle within your budget of ${maxPrice}/night."; + } + + // Build response + var result = new StringBuilder(); + result.AppendLine($"Available hotels in Seattle from {checkInDate} to {checkOutDate} ({nights} nights):"); + result.AppendLine(); + + foreach (var hotel in availableHotels) + { + var totalCost = hotel.PricePerNight * nights; + result.AppendLine($"**{hotel.Name}**"); + result.AppendLine($" Location: {hotel.Location}"); + result.AppendLine($" Rating: {hotel.Rating}/5"); + result.AppendLine($" ${hotel.PricePerNight}/night (Total: ${totalCost})"); + result.AppendLine(); + } + + return result.ToString(); + } + catch (Exception ex) + { + return $"Error processing request. Details: {ex.Message}"; + } +} + +// Create chat client using AIProjectClient to get the OpenAI connection from the project +var credential = new DefaultAzureCredential(); +AIProjectClient projectClient = new AIProjectClient(new Uri(endpoint), credential); + +// Get the OpenAI connection from the project +ClientConnection connection = projectClient.GetConnection(typeof(AzureOpenAIClient).FullName!); + +if (!connection.TryGetLocatorAsUri(out Uri? openAiEndpoint) || openAiEndpoint is null) +{ + throw new InvalidOperationException("Failed to get OpenAI endpoint from project connection."); +} +openAiEndpoint = new Uri($"https://{openAiEndpoint.Host}"); +Console.WriteLine($"OpenAI Endpoint: {openAiEndpoint}"); + +var chatClient = new AzureOpenAIClient(openAiEndpoint, credential) + .GetChatClient(deploymentName) + .AsIChatClient() + .AsBuilder() + .UseOpenTelemetry(sourceName: "Agents", configure: cfg => cfg.EnableSensitiveData = false) + .Build(); + +var agent = new ChatClientAgent(chatClient, + name: "SeattleHotelAgent", + instructions: """ + You are a helpful travel assistant specializing in finding hotels in Seattle, Washington. + + When a user asks about hotels in Seattle: + 1. Ask for their check-in and check-out dates if not provided + 2. Ask about their budget preferences if not mentioned + 3. Use the GetAvailableHotels tool to find available options + 4. Present the results in a friendly, informative way + 5. Offer to help with additional questions about the hotels or Seattle + + Be conversational and helpful. If users ask about things outside of Seattle hotels, + politely let them know you specialize in Seattle hotel recommendations. + """, + tools: [AIFunctionFactory.Create(GetAvailableHotels)]) + .AsBuilder() + .UseOpenTelemetry(sourceName: "Agents", configure: cfg => cfg.EnableSensitiveData = false) + .Build(); + +Console.WriteLine("Seattle Hotel Agent Server running on http://localhost:8088"); +await agent.RunAIAgentAsync(telemetrySourceName: "Agents"); + +// Hotel record for simulated data +record Hotel(string Name, int PricePerNight, double Rating, string Location); diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/README.md b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/README.md new file mode 100644 index 0000000000..4039a846d7 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/README.md @@ -0,0 +1,166 @@ +**IMPORTANT!** All samples and other resources made available in this GitHub repository ("samples") are designed to assist in accelerating development of agents, solutions, and agent workflows for various scenarios. Review all provided resources and carefully test output behavior in the context of your use case. AI responses may be inaccurate and AI actions should be monitored with human oversight. Learn more in the transparency documents for [Agent Service](https://learn.microsoft.com/en-us/azure/ai-foundry/responsible-ai/agents/transparency-note) and [Agent Framework](https://github.com/microsoft/agent-framework/blob/main/TRANSPARENCY_FAQ.md). + +Agents, solutions, or other output you create may be subject to legal and regulatory requirements, may require licenses, or may not be suitable for all industries, scenarios, or use cases. By using any sample, you are acknowledging that any output created using those samples are solely your responsibility, and that you will comply with all applicable laws, regulations, and relevant safety standards, terms of service, and codes of conduct. + +Third-party samples contained in this folder are subject to their own designated terms, and they have not been tested or verified by Microsoft or its affiliates. + +Microsoft has no responsibility to you or others with respect to any of these samples or any resulting output. + +# What this sample demonstrates + +This sample demonstrates a **key advantage of code-based hosted agents**: + +- **Local C# tool execution** - Run custom C# methods as agent tools + +Code-based agents can execute **any C# code** you write. This sample includes a Seattle Hotel Agent with a `GetAvailableHotels` tool that searches for available hotels based on check-in/check-out dates and budget preferences. + +The agent is hosted using the [Azure AI AgentServer SDK](https://learn.microsoft.com/en-us/dotnet/api/overview/azure/ai.agentserver.agentframework-readme) and can be deployed to Microsoft Foundry. + +## How It Works + +### Local Tools Integration + +In [Program.cs](Program.cs), the agent uses a local C# method (`GetAvailableHotels`) that simulates a hotel availability API. This demonstrates how code-based agents can execute custom server-side logic that prompt agents cannot access. + +The tool accepts: + +- **checkInDate** - Check-in date in YYYY-MM-DD format +- **checkOutDate** - Check-out date in YYYY-MM-DD format +- **maxPrice** - Maximum price per night in USD (optional, defaults to $500) + +### Agent Hosting + +The agent is hosted using the [Azure AI AgentServer SDK](https://learn.microsoft.com/en-us/dotnet/api/overview/azure/ai.agentserver.agentframework-readme), +which provisions a REST API endpoint compatible with the OpenAI Responses protocol. + +## Running the Agent Locally + +### Prerequisites + +Before running this sample, ensure you have: + +1. **Azure AI Foundry Project** + - Project created. + - Chat model deployed (e.g., `gpt-4o` or `gpt-4.1`) + - Note your project endpoint URL and model deployment name + +2. **Azure CLI** + - Installed and authenticated + - Run `az login` and verify with `az account show` + +3. **.NET 10.0 SDK or later** + - Verify your version: `dotnet --version` + - Download from [https://dotnet.microsoft.com/download](https://dotnet.microsoft.com/download) + +### Environment Variables + +Set the following environment variables (matching `agent.yaml`): + +- `AZURE_AI_PROJECT_ENDPOINT` - Your Azure AI Foundry project endpoint URL (required) +- `MODEL_DEPLOYMENT_NAME` - The deployment name for your chat model (defaults to `gpt-4.1-mini`) + +**PowerShell:** + +```powershell +# Replace with your actual values +$env:AZURE_AI_PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" +$env:MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +``` + +**Bash:** + +```bash +export AZURE_AI_PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" +export MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +``` + +### Running the Sample + +To run the agent, execute the following command in your terminal: + +```bash +dotnet restore +dotnet build +dotnet run +``` + +This will start the hosted agent locally on `http://localhost:8088/`. + +### Interacting with the Agent + +**VS Code:** + +1. Open the Visual Studio Code Command Palette and execute the `Microsoft Foundry: Open Container Agent Playground Locally` command. +2. Execute the following commands to start the containerized hosted agent. + + ```bash + dotnet restore + dotnet build + dotnet run + ``` + +3. Submit a request to the agent through the playground interface. For example, you may enter a prompt such as: "I need a hotel in Seattle from 2025-03-15 to 2025-03-18, budget under $200 per night." +4. The agent will use the GetAvailableHotels tool to search for available hotels matching your criteria. + +> **Note**: Open the local playground before starting the container agent to ensure the visualization functions correctly. + +**PowerShell (Windows):** + +```powershell +$body = @{ + input = "I need a hotel in Seattle from 2025-03-15 to 2025-03-18, budget under `$200 per night" + stream = $false +} | ConvertTo-Json + +Invoke-RestMethod -Uri http://localhost:8088/responses -Method Post -Body $body -ContentType "application/json" +``` + +**Bash/curl (Linux/macOS):** + +```bash +curl -sS -H "Content-Type: application/json" -X POST http://localhost:8088/responses \ + -d '{"input": "Find me hotels in Seattle for March 20-23, 2025 under $200 per night","stream":false}' +``` + +You can also use the `run-requests.http` file in this directory with the VS Code REST Client extension. + +The agent will use the `GetAvailableHotels` tool to search for available hotels matching your criteria. + +## Deploying the Agent to Microsoft Foundry + +**Preparation (required)** + +Please check the environment_variables section in [agent.yaml](agent.yaml) and ensure the variables there are set in your target Microsoft Foundry Project. + +To deploy the hosted agent: + +1. Open the VS Code Command Palette and run the `Microsoft Foundry: Deploy Hosted Agent` command. +2. Follow the interactive deployment prompts. The extension will help you select or create the container files it needs. +3. After deployment completes, the hosted agent appears under the `Hosted Agents (Preview)` section of the extension tree. You can select the agent there to view details and test it using the integrated playground. + +**What the deploy flow does for you:** + +- Creates or obtains an Azure Container Registry for the target project. +- Builds and pushes a container image from your workspace (the build packages the workspace respecting `.dockerignore`). +- Creates an agent version in Microsoft Foundry using the built image. If a `.env` file exists at the workspace root, the extension will parse it and include its key/value pairs as the hosted agent's environment variables in the create request (these variables will be available to the agent runtime). +- Starts the agent container on the project's capability host. If the capability host is not provisioned, the extension will prompt you to enable it and will guide you through creating it. + +## MSI Configuration in the Azure Portal + +This sample requires the Microsoft Foundry Project to authenticate using a Managed Identity when running remotely in Azure. Grant the project's managed identity the required permissions by assigning the built-in [Azure AI User](https://aka.ms/foundry-ext-project-role) role. + +To configure the Managed Identity: + +1. In the Azure Portal, open the Foundry Project. +2. Select "Access control (IAM)" from the left-hand menu. +3. Click "Add" and choose "Add role assignment". +4. In the role selection, search for and select "Azure AI User", then click "Next". +5. For "Assign access to", choose "Managed identity". +6. Click "Select members", locate the managed identity associated with your Foundry Project (you can search by the project name), then click "Select". +7. Click "Review + assign" to complete the assignment. +8. Allow a few minutes for the role assignment to propagate before running the application. + +## Additional Resources + +- [Microsoft Agents Framework](https://learn.microsoft.com/en-us/agent-framework/overview/agent-framework-overview) +- [Managed Identities for Azure Resources](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/) diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/agent.yaml b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/agent.yaml new file mode 100644 index 0000000000..5ebcf03cd8 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/agent.yaml @@ -0,0 +1,25 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml + +kind: hosted +name: dotnet-single +description: > + A travel assistant agent that helps users find hotels in Seattle. + Demonstrates local C# tool execution - a key advantage of code-based + hosted agents over prompt agents. +metadata: + authors: + - Microsoft + tags: + - Azure AI AgentServer + - Microsoft Agent Framework + - Local Tools + - Travel Assistant + - Hotel Search +protocols: + - protocol: responses + version: v1 +environment_variables: + - name: PROJECT_ENDPOINT + value: "{{AZURE_AI_PROJECT_ENDPOINT}}" + - name: MODEL_DEPLOYMENT_NAME + value: "{{MODEL_DEPLOYMENT_NAME}}" \ No newline at end of file diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/dotnetsingle.csproj b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/dotnetsingle.csproj new file mode 100644 index 0000000000..d714c09052 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/dotnetsingle.csproj @@ -0,0 +1,16 @@ + + + Exe + net10.0 + enable + enable + true + + + + + + + + + diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/run-requests.http b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/run-requests.http new file mode 100644 index 0000000000..4f2e87e097 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/run-requests.http @@ -0,0 +1,52 @@ +@host = http://localhost:8088 +@endpoint = {{host}}/responses + +### Health Check +GET {{host}}/readiness + +### Simple hotel search - budget under $200 +POST {{endpoint}} +Content-Type: application/json + +{ + "input": "I need a hotel in Seattle from 2025-03-15 to 2025-03-18, budget under $200 per night", + "stream": false +} + +### Hotel search with higher budget +POST {{endpoint}} +Content-Type: application/json + +{ + "input": "Find me hotels in Seattle for March 20-23, 2025 under $250 per night", + "stream": false +} + +### Ask for recommendations without dates (agent should ask for clarification) +POST {{endpoint}} +Content-Type: application/json + +{ + "input": "What hotels do you recommend in Seattle?", + "stream": false +} + +### Explicit input format +POST {{endpoint}} +Content-Type: application/json + +{ + "input": [ + { + "type": "message", + "role": "user", + "content": [ + { + "type": "input_text", + "text": "I'm looking for a hotel in Seattle from 2025-04-01 to 2025-04-05, my budget is $150 per night maximum" + } + ] + } + ], + "stream": false +} diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/Dockerfile b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/Dockerfile new file mode 100644 index 0000000000..413c6acb62 --- /dev/null +++ b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/Dockerfile @@ -0,0 +1,15 @@ +FROM python:3.12-slim + +WORKDIR /app + +COPY ./ . + +RUN if [ -f requirements.txt ]; then \ + pip install --no-cache-dir -r requirements.txt; \ + else \ + echo "No requirements.txt found"; \ + fi + +EXPOSE 8088 + +CMD ["python", "main.py"] diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md new file mode 100644 index 0000000000..3fd239efa8 --- /dev/null +++ b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md @@ -0,0 +1,204 @@ +**IMPORTANT!** All samples and other resources made available in this GitHub repository ("samples") are designed to assist in accelerating development of agents, solutions, and agent workflows for various scenarios. Review all provided resources and carefully test output behavior in the context of your use case. AI responses may be inaccurate and AI actions should be monitored with human oversight. Learn more in the transparency documents for [Agent Service](https://learn.microsoft.com/en-us/azure/ai-foundry/responsible-ai/agents/transparency-note) and [Agent Framework](https://github.com/microsoft/agent-framework/blob/main/TRANSPARENCY_FAQ.md). + +Agents, solutions, or other output you create may be subject to legal and regulatory requirements, may require licenses, or may not be suitable for all industries, scenarios, or use cases. By using any sample, you are acknowledging that any output created using those samples are solely your responsibility, and that you will comply with all applicable laws, regulations, and relevant safety standards, terms of service, and codes of conduct. + +Third-party samples contained in this folder are subject to their own designated terms, and they have not been tested or verified by Microsoft or its affiliates. + +Microsoft has no responsibility to you or others with respect to any of these samples or any resulting output. + +# What this sample demonstrates + +This sample demonstrates a **key advantage of code-based hosted agents**: + +- **Multi-agent workflows** - Orchestrate multiple agents working together + +Code-based agents can execute **any Python code** you write. This sample includes a **Writer-Reviewer workflow** where two agents collaborate: a Writer creates content and a Reviewer provides feedback. + +The agent is hosted using the [Azure AI AgentServer SDK](https://pypi.org/project/azure-ai-agentserver-agentframework/) and can be deployed to Microsoft Foundry. + +## How It Works + +### Multi-Agent Workflow + +In [main.py](main.py), the sample creates two agents: + +- **Writer** - An agent that creates and edits content based on feedback +- **Reviewer** - An agent that provides actionable feedback on the content + +The `WorkflowBuilder` connects these agents in a sequential flow: + +1. The Writer receives the initial request and generates content +2. The Reviewer evaluates the content and provides feedback +3. Both agent responses are output to the user. + +### Agent Hosting + +The agent is hosted using the [Azure AI AgentServer SDK](https://pypi.org/project/azure-ai-agentserver-agentframework/), +which provisions a REST API endpoint compatible with the OpenAI Responses protocol. + +## Running the Agent Locally + +### Prerequisites + +Before running this sample, ensure you have: + +1. **Microsoft Foundry Project** + - A Microsoft Project created. + - Chat model deployed (e.g., `gpt-4o` or `gpt-4.1`). + - Note your project endpoint URL and model deployment name. + +2. **Azure CLI** + - Installed and authenticated + - Run `az login` and verify with `az account show` + +3. **Python 3.10 or higher** + - Verify your version: `python --version` + - If you have Python 3.9 or older, install a newer version: + - Windows: `winget install Python.Python.3.12` + - macOS: `brew install python@3.12` + - Linux: Use your package manager + +### Environment Variables + +Set the following environment variables: + +- `PROJECT_ENDPOINT` - Your Microsoft Foundry project endpoint URL (required) +- `MODEL_DEPLOYMENT_NAME` - The deployment name for your chat model (defaults to `gpt-4.1-mini`) + +This sample loads environment variables from a local `.env` file if present. + +Create a `.env` file in this directory with the following content: + +``` +PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ +MODEL_DEPLOYMENT_NAME=gpt-4.1-mini +``` + +Or set them via PowerShell: + +```powershell +# Replace with your actual values +$env:PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" +$env:MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +``` + +### Setting Up a Virtual Environment + +It's recommended to use a virtual environment to isolate project dependencies: + +**macOS/Linux:** + +```bash +python -m venv .venv +source .venv/bin/activate +``` + +**Windows (PowerShell):** + +```powershell +python -m venv .venv +.\.venv\Scripts\Activate.ps1 +``` + +### Installing Dependencies + +Install the required Python dependencies using pip: + +```bash +pip install -r requirements.txt +``` + +The required packages are: + +- `azure-ai-agentserver-agentframework` - Agent Framework and AgentServer SDK + +### Running the Sample + +### Option 1: Press F5 (Recommended) + +Press **F5** in VS Code to start debugging. Alternatively, you can use the VS Code debug menu: + +1. Open the **Run and Debug** view (Ctrl+Shift+D / Cmd+Shift+D) +2. Select **"Debug Local Workflow HTTP Server"** from the dropdown +3. Click the green **Start Debugging** button (or press F5) + +This will: + +1. Start the HTTP server with debugging enabled +2. Open the AI Toolkit Agent Inspector for interactive testing +3. Allow you to set breakpoints and inspect the workflow + +### Option 2: Run in Terminal + +Run as HTTP server (default): + +```bash +python main.py +``` + +This will start the hosted agent locally on `http://localhost:8088/`. + +**PowerShell (Windows):** + +```powershell +$body = @{ + input = "Create a slogan for a new electric SUV that is affordable and fun to drive" + stream = $false +} | ConvertTo-Json + +Invoke-RestMethod -Uri http://localhost:8088/responses -Method Post -Body $body -ContentType "application/json" +``` + +**Bash/curl (Linux/macOS):** + +```bash +curl -sS -H "Content-Type: application/json" -X POST http://localhost:8088/responses \ + -d '{"input": "Create a slogan for a new electric SUV that is affordable and fun to drive","stream":false}' +``` + +The agent will respond with both the Writer's slogan and the Reviewer's feedback. + +Or run in CLI mode for quick testing: + +```bash +python main.py --cli +``` + +## Deploying the Agent to Microsoft Foundry + +To deploy the hosted agent: + +1. Open the VS Code Command Palette and run the `Microsoft Foundry: Deploy Hosted Agent` command. + +2. Follow the interactive deployment prompts. The extension will help you select or create the container files it needs: + - It first looks for a Dockerfile at the repository root. If not found, you can select an existing Dockerfile or generate a new one. + - If you choose to generate a Dockerfile, the extension will place the files at the repo root and open the Dockerfile in the editor; the deployment flow is intentionally cancelled in that case so you can review and edit the generated files before re-running the deploy command. + +3. After deployment completes, the hosted agent appears under the `Hosted Agents (Preview)` section of the extension tree. You can select the agent there to view details and test it using the integrated playground. + +**What the deploy flow does for you:** + +- Creates or obtains an Azure Container Registry for the target project. +- Builds and pushes a container image from your workspace (the build packages the workspace respecting `.dockerignore`). +- Creates an agent version in Microsoft Foundry using the built image. If a `.env` file exists at the workspace root, the extension will parse it and include its key/value pairs as the hosted agent's environment variables in the create request (these variables will be available to the agent runtime). +- Starts the agent container on the project's capability host. If the capability host is not provisioned, the extension will prompt you to enable it and will guide you through creating it. + +### MSI Configuration in the Azure Portal + +This sample requires the Microsoft Foundry Project to authenticate using a Managed Identity when running remotely in Azure. Grant the project's managed identity the required permissions by assigning the built-in [Azure AI User](https://aka.ms/foundry-ext-project-role) role. + +To configure the Managed Identity: + +1. In the Azure Portal, open the Foundry Project. +2. Select "Access control (IAM)" from the left-hand menu. +3. Click "Add" and choose "Add role assignment". +4. In the role selection, search for and select "Azure AI User", then click "Next". +5. For "Assign access to", choose "Managed identity". +6. Click "Select members", locate the managed identity associated with your Foundry Project (you can search by the project name), then click "Select". +7. Click "Review + assign" to complete the assignment. +8. Allow a few minutes for the role assignment to propagate before running the application. + +## Additional Resources + +- [Microsoft Agents Framework](https://learn.microsoft.com/en-us/agent-framework/overview/agent-framework-overview) +- [Managed Identities for Azure Resources](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/) diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml new file mode 100644 index 0000000000..9246218e02 --- /dev/null +++ b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml @@ -0,0 +1,24 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml + +kind: hosted +name: python-multiagent +description: > + A multi-agent workflow featuring a Writer and Reviewer that collaborate + to create and refine content. +metadata: + authors: + - Microsoft + tags: + - Azure AI AgentServer + - Microsoft Agent Framework + - Multi-Agent Workflow + - Writer-Reviewer + - Content Creation +protocols: + - protocol: responses + version: v1 +environment_variables: + - name: PROJECT_ENDPOINT + value: "{{PROJECT_ENDPOINT}}" + - name: MODEL_DEPLOYMENT_NAME + value: "{{MODEL_DEPLOYMENT_NAME}}" diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py new file mode 100644 index 0000000000..63658879f1 --- /dev/null +++ b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py @@ -0,0 +1,107 @@ +import asyncio +import os +import sys +from contextlib import asynccontextmanager + +from agent_framework import WorkflowBuilder +from agent_framework.azure import AzureAIAgentClient +from azure.identity.aio import DefaultAzureCredential, ManagedIdentityCredential +from dotenv import load_dotenv + +load_dotenv(override=True) + +# Configure these for your Foundry project +# Read the explicit variables present in the .env file +PROJECT_ENDPOINT = os.getenv( + "PROJECT_ENDPOINT" +) # e.g., "https://.services.ai.azure.com" +MODEL_DEPLOYMENT_NAME = os.getenv( + "MODEL_DEPLOYMENT_NAME", "gpt-4.1-mini" +) # Your model deployment name e.g., "gpt-4.1-mini" + + +def get_credential(): + """Will use Managed Identity when running in Azure, otherwise falls back to DefaultAzureCredential.""" + return ( + ManagedIdentityCredential() + if os.getenv("MSI_ENDPOINT") + else DefaultAzureCredential() + ) + + +@asynccontextmanager +async def create_agents(): + async with ( + get_credential() as credential, + AzureAIAgentClient( + project_endpoint=PROJECT_ENDPOINT, + model_deployment_name=MODEL_DEPLOYMENT_NAME, + credential=credential, + ) as writer_client, + AzureAIAgentClient( + project_endpoint=PROJECT_ENDPOINT, + model_deployment_name=MODEL_DEPLOYMENT_NAME, + credential=credential, + ) as reviewer_client, + ): + writer = writer_client.create_agent( + name="Writer", + instructions="You are an excellent content writer. You create new content and edit contents based on the feedback.", + ) + reviewer = reviewer_client.create_agent( + name="Reviewer", + instructions="You are an excellent content reviewer. Provide actionable feedback to the writer about the provided content in the most concise manner possible.", + ) + yield writer, reviewer + + +def create_workflow(writer, reviewer): + workflow = ( + WorkflowBuilder(name="Writer-Reviewer") + .register_agent(lambda: writer, name="Writer", output_response=True) + .register_agent(lambda: reviewer, name="Reviewer", output_response=True) + .set_start_executor("Writer") + .add_edge("Writer", "Reviewer") + .build() + ) + return workflow.as_agent() + + +async def main() -> None: + """ + The writer and reviewer multi-agent workflow. + + Usage: + python main.py # Run in server mode + + Environment variables required: + - PROJECT_ENDPOINT: Your Microsoft Foundry project endpoint + - MODEL_DEPLOYMENT_NAME: Your Microsoft Foundry model deployment name + """ + + async with create_agents() as (writer, reviewer): + agent = create_workflow(writer, reviewer) + + # Check if running in CLI mode (default is server mode) + if "--cli" in sys.argv: + # CLI mode for testing + print("Running workflow agent in CLI mode...") + + # Test with a sample query + user_message = "Create a slogan for a new electric SUV that is affordable and fun to drive." + print(f"\nUser: {user_message}\n") + + response = await agent.run(user_message) + for msg in response.messages: + if msg.text: + print(f"{msg.author_name}: {msg.text}\n") + else: + # Server mode (default) + print("Starting workflow agent HTTP server...") + from azure.ai.agentserver.agentframework import from_agent_framework + + await from_agent_framework(agent).run_async() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt new file mode 100644 index 0000000000..e2e7cd2f65 --- /dev/null +++ b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt @@ -0,0 +1,4 @@ +azure-ai-agentserver-agentframework==1.0.0b14 +debugpy +# Agent development CLI tool (preview) +agent-dev-cli \ No newline at end of file diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/Dockerfile b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/Dockerfile new file mode 100644 index 0000000000..413c6acb62 --- /dev/null +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/Dockerfile @@ -0,0 +1,15 @@ +FROM python:3.12-slim + +WORKDIR /app + +COPY ./ . + +RUN if [ -f requirements.txt ]; then \ + pip install --no-cache-dir -r requirements.txt; \ + else \ + echo "No requirements.txt found"; \ + fi + +EXPOSE 8088 + +CMD ["python", "main.py"] diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md new file mode 100644 index 0000000000..fc6e876268 --- /dev/null +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md @@ -0,0 +1,195 @@ +**IMPORTANT!** All samples and other resources made available in this GitHub repository ("samples") are designed to assist in accelerating development of agents, solutions, and agent workflows for various scenarios. Review all provided resources and carefully test output behavior in the context of your use case. AI responses may be inaccurate and AI actions should be monitored with human oversight. Learn more in the transparency documents for [Agent Service](https://learn.microsoft.com/en-us/azure/ai-foundry/responsible-ai/agents/transparency-note) and [Agent Framework](https://github.com/microsoft/agent-framework/blob/main/TRANSPARENCY_FAQ.md). + +Agents, solutions, or other output you create may be subject to legal and regulatory requirements, may require licenses, or may not be suitable for all industries, scenarios, or use cases. By using any sample, you are acknowledging that any output created using those samples are solely your responsibility, and that you will comply with all applicable laws, regulations, and relevant safety standards, terms of service, and codes of conduct. + +Third-party samples contained in this folder are subject to their own designated terms, and they have not been tested or verified by Microsoft or its affiliates. + +Microsoft has no responsibility to you or others with respect to any of these samples or any resulting output. + +# What this sample demonstrates + +This sample demonstrates a **key advantage of code-based hosted agents**: + +- **Local Python tool execution** - Run custom Python functions as agent tools + +Code-based agents can execute **any Python code** you write. This sample includes a Seattle Hotel Agent with a `get_available_hotels` tool that searches for available hotels based on check-in/check-out dates and budget preferences. + +The agent is hosted using the [Azure AI AgentServer SDK](https://pypi.org/project/azure-ai-agentserver-agentframework/) and can be deployed to Microsoft Foundry. + +## How It Works + +### Local Tools Integration + +In [main.py](main.py), the agent uses a local Python function (`get_available_hotels`) that simulates a hotel availability API. This demonstrates how code-based agents can execute custom server-side logic that prompt agents cannot access. + +The tool accepts: + +- **check_in_date** - Check-in date in YYYY-MM-DD format +- **check_out_date** - Check-out date in YYYY-MM-DD format +- **max_price** - Maximum price per night in USD (optional, defaults to $500) + +### Agent Hosting + +The agent is hosted using the [Azure AI AgentServer SDK](https://pypi.org/project/azure-ai-agentserver-agentframework/), +which provisions a REST API endpoint compatible with the OpenAI Responses protocol. + +## Running the Agent Locally + +### Prerequisites + +Before running this sample, ensure you have: + +1. **Microsoft Foundry Project** + - A Microsoft Project created. + - Chat model deployed (e.g., `gpt-4o` or `gpt-4.1`). + - Note your project endpoint URL and model deployment name. + +2. **Azure CLI** + - Installed and authenticated + - Run `az login` and verify with `az account show` + +3. **Python 3.10 or higher** + - Verify your version: `python --version` + - If you have Python 3.9 or older, install a newer version: + - Windows: `winget install Python.Python.3.12` + - macOS: `brew install python@3.12` + - Linux: Use your package manager + +### Environment Variables + +Set the following environment variables: + +- `PROJECT_ENDPOINT` - Your Microsoft Foundry project endpoint URL (required) +- `MODEL_DEPLOYMENT_NAME` - The deployment name for your chat model (defaults to `gpt-4.1-mini`) + +This sample loads environment variables from a local `.env` file if present. + +Create a `.env` file in this directory with the following content: + +``` +PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ +MODEL_DEPLOYMENT_NAME=gpt-4.1-mini +``` + +Or set them via PowerShell: + +```powershell +# Replace with your actual values +$env:PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" +$env:MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +``` + +### Setting Up a Virtual Environment + +It's recommended to use a virtual environment to isolate project dependencies: + +**macOS/Linux:** + +```bash +python -m venv .venv +source .venv/bin/activate +``` + +**Windows (PowerShell):** + +```powershell +python -m venv .venv +.\.venv\Scripts\Activate.ps1 +``` + +### Installing Dependencies + +Install the required Python dependencies using pip: + +```bash +pip install -r requirements.txt +``` + +The required packages are: + +- `azure-ai-agentserver-agentframework` - Agent Framework and AgentServer SDK + +### Running the Sample + +#### Option 1: Press F5 (Recommended) + +Press **F5** in VS Code to start debugging. Alternatively, you can use the VS Code debug menu: + +1. Open the **Run and Debug** view (Ctrl+Shift+D / Cmd+Shift+D) +2. Select **"Debug Local Workflow HTTP Server"** from the dropdown +3. Click the green **Start Debugging** button (or press F5) + +This will: + +1. Start the HTTP server with debugging enabled +2. Open the AI Toolkit Agent Inspector for interactive testing +3. Allow you to set breakpoints and inspect the workflow + +#### Option 2: Run in Terminal + +Run as HTTP server (default): + +```bash +python main.py +``` + +This will start the hosted agent locally on `http://localhost:8088/`. + +**PowerShell (Windows):** + +```powershell +$body = @{ + input = "I need a hotel in Seattle from 2025-03-15 to 2025-03-18, budget under `$200 per night" + stream = $false +} | ConvertTo-Json + +Invoke-RestMethod -Uri http://localhost:8088/responses -Method Post -Body $body -ContentType "application/json" +``` + +**Bash/curl (Linux/macOS):** + +```bash +curl -sS -H "Content-Type: application/json" -X POST http://localhost:8088/responses \ + -d '{"input": "Find me hotels in Seattle for March 20-23, 2025 under $200 per night","stream":false}' +``` + +The agent will use the `get_available_hotels` tool to search for available hotels matching your criteria. + +## Deploying the Agent to Microsoft Foundry + +To deploy the hosted agent: + +1. Open the VS Code Command Palette and run the `Microsoft Foundry: Deploy Hosted Agent` command. + +2. Follow the interactive deployment prompts. The extension will help you select or create the container files it needs: + - It first looks for a Dockerfile at the repository root. If not found, you can select an existing Dockerfile or generate a new one. + - If you choose to generate a Dockerfile, the extension will place the files at the repo root and open the Dockerfile in the editor; the deployment flow is intentionally cancelled in that case so you can review and edit the generated files before re-running the deploy command. + +3. After deployment completes, the hosted agent appears under the `Hosted Agents (Preview)` section of the extension tree. You can select the agent there to view details and test it using the integrated playground. + +**What the deploy flow does for you:** + +- Creates or obtains an Azure Container Registry for the target project. +- Builds and pushes a container image from your workspace (the build packages the workspace respecting `.dockerignore`). +- Creates an agent version in Microsoft Foundry using the built image. If a `.env` file exists at the workspace root, the extension will parse it and include its key/value pairs as the hosted agent's environment variables in the create request (these variables will be available to the agent runtime). +- Starts the agent container on the project's capability host. If the capability host is not provisioned, the extension will prompt you to enable it and will guide you through creating it. + +### MSI Configuration in the Azure Portal + +This sample requires the Microsoft Foundry Project to authenticate using a Managed Identity when running remotely in Azure. Grant the project's managed identity the required permissions by assigning the built-in [Azure AI User](https://aka.ms/foundry-ext-project-role) role. + +To configure the Managed Identity: + +1. In the Azure Portal, open the Foundry Project. +2. Select "Access control (IAM)" from the left-hand menu. +3. Click "Add" and choose "Add role assignment". +4. In the role selection, search for and select "Azure AI User", then click "Next". +5. For "Assign access to", choose "Managed identity". +6. Click "Select members", locate the managed identity associated with your Foundry Project (you can search by the project name), then click "Select". +7. Click "Review + assign" to complete the assignment. +8. Allow a few minutes for the role assignment to propagate before running the application. + +## Additional Resources + +- [Microsoft Agents Framework](https://learn.microsoft.com/en-us/agent-framework/overview/agent-framework-overview) +- [Managed Identities for Azure Resources](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/) diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml new file mode 100644 index 0000000000..9967f88ff1 --- /dev/null +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml @@ -0,0 +1,25 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml + +kind: hosted +name: python-single +description: > + A travel assistant agent that helps users find hotels in Seattle. + Demonstrates local Python tool execution - a key advantage of code-based + hosted agents over prompt agents. +metadata: + authors: + - Microsoft + tags: + - Azure AI AgentServer + - Microsoft Agent Framework + - Local Tools + - Travel Assistant + - Hotel Search +protocols: + - protocol: responses + version: v1 +environment_variables: + - name: PROJECT_ENDPOINT + value: "{{PROJECT_ENDPOINT}}" + - name: MODEL_DEPLOYMENT_NAME + value: "{{MODEL_DEPLOYMENT_NAME}}" \ No newline at end of file diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py new file mode 100644 index 0000000000..19acbddcde --- /dev/null +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py @@ -0,0 +1,149 @@ +""" +Seattle Hotel Agent - A simple agent with a tool to find hotels in Seattle. +Uses Microsoft Agent Framework with Azure AI Foundry. +Ready for deployment to Foundry Hosted Agent service. +""" + +import asyncio +import os +from datetime import datetime +from typing import Annotated + +from dotenv import load_dotenv + +load_dotenv(override=True) + +from agent_framework.azure import AzureAIAgentClient +from azure.ai.agentserver.agentframework import from_agent_framework +from azure.identity.aio import DefaultAzureCredential + +# Configure these for your Foundry project +# Read the explicit variables present in the .env file +PROJECT_ENDPOINT = os.getenv( + "PROJECT_ENDPOINT" +) # e.g., "https://.services.ai.azure.com" +MODEL_DEPLOYMENT_NAME = os.getenv( + "MODEL_DEPLOYMENT_NAME", "gpt-4.1-mini" +) # Your model deployment name e.g., "gpt-4.1-mini" + + +# Simulated hotel data for Seattle +SEATTLE_HOTELS = [ + { + "name": "Contoso Suites", + "price_per_night": 189, + "rating": 4.5, + "location": "Downtown", + }, + { + "name": "Fabrikam Residences", + "price_per_night": 159, + "rating": 4.2, + "location": "Pike Place Market", + }, + { + "name": "Alpine Ski House", + "price_per_night": 249, + "rating": 4.7, + "location": "Seattle Center", + }, + { + "name": "Margie's Travel Lodge", + "price_per_night": 219, + "rating": 4.4, + "location": "Waterfront", + }, + { + "name": "Northwind Inn", + "price_per_night": 139, + "rating": 4.0, + "location": "Capitol Hill", + }, + { + "name": "Relecloud Hotel", + "price_per_night": 99, + "rating": 3.8, + "location": "University District", + }, +] + + +def get_available_hotels( + check_in_date: Annotated[str, "Check-in date in YYYY-MM-DD format"], + check_out_date: Annotated[str, "Check-out date in YYYY-MM-DD format"], + max_price: Annotated[int, "Maximum price per night in USD (optional)"] = 500, +) -> str: + """ + Get available hotels in Seattle for the specified dates. + This simulates a call to a fake hotel availability API. + """ + try: + # Parse dates + check_in = datetime.strptime(check_in_date, "%Y-%m-%d") + check_out = datetime.strptime(check_out_date, "%Y-%m-%d") + + # Validate dates + if check_out <= check_in: + return "Error: Check-out date must be after check-in date." + + nights = (check_out - check_in).days + + # Filter hotels by price + available_hotels = [ + hotel for hotel in SEATTLE_HOTELS if hotel["price_per_night"] <= max_price + ] + + if not available_hotels: + return ( + f"No hotels found in Seattle within your budget of ${max_price}/night." + ) + + # Build response + result = f"Available hotels in Seattle from {check_in_date} to {check_out_date} ({nights} nights):\n\n" + + for hotel in available_hotels: + total_cost = hotel["price_per_night"] * nights + result += f"**{hotel['name']}**\n" + result += f" Location: {hotel['location']}\n" + result += f" Rating: {hotel['rating']}/5\n" + result += f" ${hotel['price_per_night']}/night (Total: ${total_cost})\n\n" + + return result + + except ValueError as e: + return f"Error parsing dates. Please use YYYY-MM-DD format. Details: {str(e)}" + + +async def main(): + """Main function to run the agent as a web server.""" + async with ( + DefaultAzureCredential() as credential, + AzureAIAgentClient( + project_endpoint=PROJECT_ENDPOINT, + model_deployment_name=MODEL_DEPLOYMENT_NAME, + credential=credential, + ) as client, + ): + agent = client.create_agent( + name="SeattleHotelAgent", + instructions="""You are a helpful travel assistant specializing in finding hotels in Seattle, Washington. + +When a user asks about hotels in Seattle: +1. Ask for their check-in and check-out dates if not provided +2. Ask about their budget preferences if not mentioned +3. Use the get_available_hotels tool to find available options +4. Present the results in a friendly, informative way +5. Offer to help with additional questions about the hotels or Seattle + +Be conversational and helpful. If users ask about things outside of Seattle hotels, +politely let them know you specialize in Seattle hotel recommendations.""", + tools=[get_available_hotels], + ) + + print("Seattle Hotel Agent Server running on http://localhost:8088") + server = from_agent_framework(agent) + await server.run_async() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt new file mode 100644 index 0000000000..e2e7cd2f65 --- /dev/null +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt @@ -0,0 +1,4 @@ +azure-ai-agentserver-agentframework==1.0.0b14 +debugpy +# Agent development CLI tool (preview) +agent-dev-cli \ No newline at end of file From 1f5ce5962856448abac95c7178ae05e04f9dd09b Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Fri, 27 Feb 2026 20:06:17 +0000 Subject: [PATCH 02/14] Align foundry extension samples with existing hosted agent patterns - Fix Python multiagent indentation bug (from_agent_framework ran in both modes) - Remove hardcoded personal endpoint from appsettings.Development.json - Rename .NET folders/projects to PascalCase (FoundryMultiAgent, FoundrySingleAgent) - Upgrade .NET multiagent from net9.0 to net10.0 - Add ManagePackageVersionsCentrally=false and analyzer blocks to .csproj files - Replace wildcard package versions with fixed versions - Use alpine Docker images and standard build pattern - Align agent.yaml structure (template nesting, displayName, resources, authors) - Convert .NET multiagent from namespace/class to top-level statements - Add run-requests.http for multiagent sample - Fix Python requirements.txt (remove dev deps, add agent-framework) - Add proper copyright headers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Dockerfile | 4 +- .../FoundryMultiAgent.csproj | 77 ++++++++ .../HostedAgents/FoundryMultiAgent/Program.cs | 102 +++++++++++ .../README.md | 4 +- .../HostedAgents/FoundryMultiAgent/agent.yaml | 31 ++++ .../appsettings.Development.json | 4 + .../FoundryMultiAgent/run-requests.http | 34 ++++ .../FoundrySingleAgent/Dockerfile | 20 +++ .../FoundrySingleAgent.csproj | 67 +++++++ .../Program.cs | 2 + .../README.md | 0 .../agent.yaml | 29 +-- .../run-requests.http | 0 .../foundry_multiagent/Dockerfile | 22 --- .../foundry_multiagent/Program.cs | 166 ------------------ .../foundry_multiagent/agent.yaml | 24 --- .../appsettings.Development.json | 4 - .../dotnetmultiagent.csproj | 30 ---- .../foundry_single_agent/dotnetsingle.csproj | 16 -- .../foundry_multiagent/agent.yaml | 31 ++-- .../hosted_agents/foundry_multiagent/main.py | 2 +- .../foundry_multiagent/requirements.txt | 4 +- .../foundry_single_agent/agent.yaml | 29 +-- .../foundry_single_agent/requirements.txt | 4 +- 24 files changed, 398 insertions(+), 308 deletions(-) rename dotnet/samples/05-end-to-end/HostedAgents/{foundry_single_agent => FoundryMultiAgent}/Dockerfile (80%) create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs rename dotnet/samples/05-end-to-end/HostedAgents/{foundry_multiagent => FoundryMultiAgent}/README.md (96%) create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/agent.yaml create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/appsettings.Development.json create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/run-requests.http create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Dockerfile create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj rename dotnet/samples/05-end-to-end/HostedAgents/{foundry_single_agent => FoundrySingleAgent}/Program.cs (99%) rename dotnet/samples/05-end-to-end/HostedAgents/{foundry_single_agent => FoundrySingleAgent}/README.md (100%) rename dotnet/samples/05-end-to-end/HostedAgents/{foundry_single_agent => FoundrySingleAgent}/agent.yaml (51%) rename dotnet/samples/05-end-to-end/HostedAgents/{foundry_single_agent => FoundrySingleAgent}/run-requests.http (100%) delete mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Dockerfile delete mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Program.cs delete mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/agent.yaml delete mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/appsettings.Development.json delete mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/dotnetmultiagent.csproj delete mode 100644 dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/dotnetsingle.csproj diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Dockerfile b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Dockerfile similarity index 80% rename from dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Dockerfile rename to dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Dockerfile index 493a4076e4..fc3d3a1a5b 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Dockerfile +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Dockerfile @@ -7,7 +7,7 @@ COPY . . RUN dotnet restore RUN dotnet build -c Release --no-restore -RUN dotnet publish -c Release --no-build -o /app +RUN dotnet publish -c Release --no-build -o /app -f net10.0 # Run the application FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final @@ -17,4 +17,4 @@ WORKDIR /app COPY --from=build /app . EXPOSE 8088 -ENTRYPOINT ["dotnet", "dotnetsingle.dll"] +ENTRYPOINT ["dotnet", "FoundryMultiAgent.dll"] diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj new file mode 100644 index 0000000000..45d3bd8be0 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj @@ -0,0 +1,77 @@ + + + Exe + net10.0 + enable + enable + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + PreserveNewest + + + + diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs new file mode 100644 index 0000000000..5ded21282a --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample demonstrates a multi-agent workflow with Writer and Reviewer agents +// using Azure AI Foundry PersistentAgentsClient and the Agent Framework WorkflowBuilder. + +using Azure.AI.Agents.Persistent; +using Azure.AI.AgentServer.AgentFramework.Extensions; +using Azure.Core; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Workflows; +using Microsoft.Extensions.AI; + +var endpoint = Environment.GetEnvironmentVariable("PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("PROJECT_ENDPOINT is not set."); +var deploymentName = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +Console.WriteLine($"Using Azure AI endpoint: {endpoint}"); +Console.WriteLine($"Using model deployment: {deploymentName}"); + +// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production. +// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid +// latency issues, unintended credential probing, and potential security risks from fallback mechanisms. +TokenCredential credential = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSI_ENDPOINT")) + ? new DefaultAzureCredential() + : new ManagedIdentityCredential(); + +// Create separate PersistentAgentsClient for each agent +var writerClient = new PersistentAgentsClient(endpoint, credential); +var reviewerClient = new PersistentAgentsClient(endpoint, credential); + +(ChatClientAgent agent, string id)? writer = null; +(ChatClientAgent agent, string id)? reviewer = null; + +try +{ + // Create Foundry agents with separate clients + writer = await CreateAgentAsync( + writerClient, + deploymentName, + "Writer", + "You are an excellent content writer. You create new content and edit contents based on the feedback." + ); + reviewer = await CreateAgentAsync( + reviewerClient, + deploymentName, + "Reviewer", + "You are an excellent content reviewer. Provide actionable feedback to the writer about the provided content. Provide the feedback in the most concise manner possible." + ); + + var workflow = new WorkflowBuilder(writer.Value.agent) + .AddEdge(writer.Value.agent, reviewer.Value.agent) + .WithOutputFrom(reviewer.Value.agent) + .Build(); + + Console.WriteLine("Starting Writer-Reviewer Workflow Agent Server on http://localhost:8088"); + await workflow.AsAgent().RunAIAgentAsync(); +} +finally +{ + // Clean up all resources + await CleanupAsync(writerClient, writer?.id); + await CleanupAsync(reviewerClient, reviewer?.id); + + if (credential is IDisposable disposable) + { + disposable.Dispose(); + } +} + +static async Task<(ChatClientAgent agent, string id)> CreateAgentAsync( + PersistentAgentsClient client, + string model, + string name, + string instructions) +{ + var agentMetadata = await client.Administration.CreateAgentAsync( + model: model, + name: name, + instructions: instructions + ); + + var chatClient = client.AsIChatClient(agentMetadata.Value.Id); + return (new ChatClientAgent(chatClient), agentMetadata.Value.Id); +} + +static async Task CleanupAsync(PersistentAgentsClient client, string? agentId) +{ + if (string.IsNullOrEmpty(agentId)) + { + return; + } + + try + { + await client.Administration.DeleteAgentAsync(agentId); + } + catch (Exception e) + { + Console.WriteLine($"Cleanup failed for agent {agentId}: {e.Message}"); + } +} diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/README.md b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md similarity index 96% rename from dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/README.md rename to dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md index fde0fb26b4..e9f35757e1 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/README.md +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md @@ -58,9 +58,7 @@ Before running this sample, ensure you have: ### Environment Variables -**Foundry VS Code Extension Users:** - -If you created your hosted agent project using the Microsoft Foundry VS Code extension, a `appsettings.Development.json` file is already created in the project root with the necessary environment variables. Double-check that the values are correct. +Set the following environment variables: **PowerShell:** diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/agent.yaml b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/agent.yaml new file mode 100644 index 0000000000..8f3abe5f53 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/agent.yaml @@ -0,0 +1,31 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml + +name: FoundryMultiAgent +displayName: "Foundry Multi-Agent Workflow" +description: > + A multi-agent workflow featuring a Writer and Reviewer that collaborate + to create and refine content using Azure AI Foundry PersistentAgentsClient. +metadata: + authors: + - Microsoft Agent Framework Team + tags: + - Azure AI AgentServer + - Microsoft Agent Framework + - Multi-Agent Workflow + - Writer-Reviewer + - Content Creation +template: + kind: hosted + name: FoundryMultiAgent + protocols: + - protocol: responses + version: v1 + environment_variables: + - name: PROJECT_ENDPOINT + value: ${PROJECT_ENDPOINT} + - name: MODEL_DEPLOYMENT_NAME + value: gpt-4o-mini +resources: + - name: "gpt-4o-mini" + kind: model + id: gpt-4o-mini diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/appsettings.Development.json b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/appsettings.Development.json new file mode 100644 index 0000000000..c5e5ebd833 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/appsettings.Development.json @@ -0,0 +1,4 @@ +{ + "PROJECT_ENDPOINT": "https://.services.ai.azure.com/api/projects/", + "MODEL_DEPLOYMENT_NAME": "gpt-4.1-mini" +} diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/run-requests.http b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/run-requests.http new file mode 100644 index 0000000000..2fcdb2499e --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/run-requests.http @@ -0,0 +1,34 @@ +@host = http://localhost:8088 +@endpoint = {{host}}/responses + +### Health Check +GET {{host}}/readiness + +### Simple string input - Content creation request +POST {{endpoint}} +Content-Type: application/json + +{ + "input": "Create a slogan for a new electric SUV that is affordable and fun to drive", + "stream": false +} + +### Explicit input format +POST {{endpoint}} +Content-Type: application/json + +{ + "input": [ + { + "type": "message", + "role": "user", + "content": [ + { + "type": "input_text", + "text": "Write a short product description for a smart water bottle that tracks hydration" + } + ] + } + ], + "stream": false +} diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Dockerfile b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Dockerfile new file mode 100644 index 0000000000..0d1141cc69 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Dockerfile @@ -0,0 +1,20 @@ +# Build the application +FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build +WORKDIR /src + +# Copy files from the current directory on the host to the working directory in the container +COPY . . + +RUN dotnet restore +RUN dotnet build -c Release --no-restore +RUN dotnet publish -c Release --no-build -o /app -f net10.0 + +# Run the application +FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final +WORKDIR /app + +# Copy everything needed to run the app from the "build" stage. +COPY --from=build /app . + +EXPOSE 8088 +ENTRYPOINT ["dotnet", "FoundrySingleAgent.dll"] diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj new file mode 100644 index 0000000000..89b952be32 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj @@ -0,0 +1,67 @@ + + + Exe + net10.0 + enable + enable + + + false + + + + + + + + + + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Program.cs b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs similarity index 99% rename from dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Program.cs rename to dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs index 5b2859632d..64465e6f34 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/Program.cs +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs @@ -1,3 +1,5 @@ +// Copyright (c) Microsoft. All rights reserved. + // Seattle Hotel Agent - A simple agent with a tool to find hotels in Seattle. // Uses Microsoft Agent Framework with Azure AI Foundry. // Ready for deployment to Foundry Hosted Agent service. diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/README.md b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/README.md similarity index 100% rename from dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/README.md rename to dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/README.md diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/agent.yaml b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/agent.yaml similarity index 51% rename from dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/agent.yaml rename to dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/agent.yaml index 5ebcf03cd8..100defd112 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/agent.yaml +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/agent.yaml @@ -1,25 +1,32 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml -kind: hosted -name: dotnet-single +name: FoundrySingleAgent +displayName: "Foundry Single Agent with Local Tools" description: > A travel assistant agent that helps users find hotels in Seattle. Demonstrates local C# tool execution - a key advantage of code-based hosted agents over prompt agents. metadata: authors: - - Microsoft + - Microsoft Agent Framework Team tags: - Azure AI AgentServer - Microsoft Agent Framework - Local Tools - Travel Assistant - Hotel Search -protocols: - - protocol: responses - version: v1 -environment_variables: - - name: PROJECT_ENDPOINT - value: "{{AZURE_AI_PROJECT_ENDPOINT}}" - - name: MODEL_DEPLOYMENT_NAME - value: "{{MODEL_DEPLOYMENT_NAME}}" \ No newline at end of file +template: + kind: hosted + name: FoundrySingleAgent + protocols: + - protocol: responses + version: v1 + environment_variables: + - name: AZURE_AI_PROJECT_ENDPOINT + value: ${AZURE_AI_PROJECT_ENDPOINT} + - name: MODEL_DEPLOYMENT_NAME + value: gpt-4o-mini +resources: + - name: "gpt-4o-mini" + kind: model + id: gpt-4o-mini \ No newline at end of file diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/run-requests.http b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/run-requests.http similarity index 100% rename from dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/run-requests.http rename to dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/run-requests.http diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Dockerfile b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Dockerfile deleted file mode 100644 index b4d16d949e..0000000000 --- a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -# Build the application -FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build -WORKDIR /src - -# Copy project files for dependency resolution -COPY *.csproj* . -RUN dotnet restore dotnetmultiagent.csproj - -# Copy files from the current directory on the host to the working directory in the container -COPY . . - -RUN dotnet publish -c Release -o /app -p:AssemblyName=app - -# Run the application -FROM mcr.microsoft.com/dotnet/aspnet:9.0 -WORKDIR /app - -# Copy everything needed to run the app from the "build" stage. -COPY --from=build /app . - -EXPOSE 8088 -ENTRYPOINT ["dotnet", "app.dll"] diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Program.cs b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Program.cs deleted file mode 100644 index df66e846f9..0000000000 --- a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/Program.cs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using Azure.AI.Agents.Persistent; -using Azure.AI.AgentServer.AgentFramework.Extensions; -using Azure.Core; -using Azure.Identity; -using Microsoft.Agents.AI; -using Microsoft.Agents.AI.Workflows; -using Microsoft.Extensions.AI; -using Microsoft.Extensions.Configuration; -using OpenTelemetry; -using OpenTelemetry.Resources; -using OpenTelemetry.Trace; - -namespace dotnetmultiagent; - -internal static class Program -{ - private static TracerProvider? s_tracerProvider; - - private static async Task Main(string[] args) - { - try - { - // Enable OpenTelemetry tracing for visualization - ConfigureObservability(); - - await RunAsync().ConfigureAwait(false); - } - catch (Exception e) - { - Console.WriteLine($"Critical error: {e}"); - } - } - - private static async ValueTask RunAsync() - { - // Build configuration - var configuration = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.Development.json", optional: true) - .AddEnvironmentVariables() - .Build(); - - var endpoint = - configuration["PROJECT_ENDPOINT"] - ?? throw new InvalidOperationException( - "PROJECT_ENDPOINT is required. Set it in appsettings.Development.json for local development or as PROJECT_ENDPOINT environment variable for production"); - var deployment = - configuration["MODEL_DEPLOYMENT_NAME"] - ?? throw new InvalidOperationException( - "MODEL_DEPLOYMENT_NAME is required. Set it in appsettings.Development.json for local development or as MODEL_DEPLOYMENT_NAME environment variable for containers"); - - Console.WriteLine($"Using Azure AI endpoint: {endpoint}"); - Console.WriteLine($"Using model deployment: {deployment}"); - - // Create credential - use ManagedIdentityCredential if MSI_ENDPOINT exists, otherwise DefaultAzureCredential - TokenCredential credential = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSI_ENDPOINT")) - ? new DefaultAzureCredential() - : new ManagedIdentityCredential(); - - // Create separate PersistentAgentsClient for each agent - var writerClient = new PersistentAgentsClient(endpoint, credential); - var reviewerClient = new PersistentAgentsClient(endpoint, credential); - - (ChatClientAgent agent, string id)? writer = null; - (ChatClientAgent agent, string id)? reviewer = null; - - try - { - // Create Foundry agents with separate clients - writer = await CreateAgentAsync( - writerClient, - deployment, - "Writer", - "You are an excellent content writer. You create new content and edit contents based on the feedback." - ); - reviewer = await CreateAgentAsync( - reviewerClient, - deployment, - "Reviewer", - "You are an excellent content reviewer. Provide actionable feedback to the writer about the provided content. Provide the feedback in the most concise manner possible." - ); - Console.WriteLine(); - - var workflow = new WorkflowBuilder(writer.Value.agent) - .AddEdge(writer.Value.agent, reviewer.Value.agent) - .WithOutputFrom(reviewer.Value.agent) - .Build(); - - Console.WriteLine("Starting Writer-Reviewer Workflow Agent Server on http://localhost:8088"); - await workflow.AsAgent().RunAIAgentAsync(); - } - catch (Exception ex) - { - Console.WriteLine($"Error running workflow: {ex.Message}"); - throw; - } - finally - { - // Clean up all resources - await CleanupAsync(writerClient, writer?.id); - await CleanupAsync(reviewerClient, reviewer?.id); - - if (credential is IDisposable disposable) - { - disposable.Dispose(); - } - } - } - - private static async Task<(ChatClientAgent agent, string id)> CreateAgentAsync( - PersistentAgentsClient client, - string model, - string name, - string instructions) - { - var agentMetadata = await client.Administration.CreateAgentAsync( - model: model, - name: name, - instructions: instructions - ); - - var chatClient = client.AsIChatClient(agentMetadata.Value.Id); - return (new ChatClientAgent(chatClient), agentMetadata.Value.Id); - } - - private static async Task CleanupAsync(PersistentAgentsClient client, string? agentId) - { - if (string.IsNullOrEmpty(agentId)) - { - return; - } - - try - { - await client.Administration.DeleteAgentAsync(agentId); - } - catch (Exception e) - { - Console.WriteLine($"Cleanup failed for agent {agentId}: {e.Message}"); - } - } - - private static void ConfigureObservability() - { - var otlpEndpoint = - Environment.GetEnvironmentVariable("OTLP_ENDPOINT") ?? "http://localhost:4319"; - - var resourceBuilder = ResourceBuilder.CreateDefault() - .AddService("WorkflowSample"); - - s_tracerProvider = Sdk.CreateTracerProviderBuilder() - .SetResourceBuilder(resourceBuilder) - .AddSource("Microsoft.Agents.AI.*") // All agent framework sources - .SetSampler(new AlwaysOnSampler()) // Ensure all traces are sampled - .AddOtlpExporter(options => - { - options.Endpoint = new Uri(otlpEndpoint); - options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc; - }) - .Build(); - - Console.WriteLine($"OpenTelemetry configured. OTLP endpoint: {otlpEndpoint}"); - } -} diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/agent.yaml b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/agent.yaml deleted file mode 100644 index 809524dc9a..0000000000 --- a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/agent.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml - -kind: hosted -name: dotnet-multiagent -description: > - A multi-agent workflow featuring a Writer and Reviewer that collaborate - to create and refine content. -metadata: - authors: - - Microsoft - tags: - - Azure AI AgentServer - - Microsoft Agent Framework - - Multi-Agent Workflow - - Writer-Reviewer - - Content Creation -protocols: - - protocol: responses - version: v1 -environment_variables: - - name: PROJECT_ENDPOINT - value: "{{PROJECT_ENDPOINT}}" - - name: MODEL_DEPLOYMENT_NAME - value: "{{MODEL_DEPLOYMENT_NAME}}" diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/appsettings.Development.json b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/appsettings.Development.json deleted file mode 100644 index 270a481008..0000000000 --- a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/appsettings.Development.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "PROJECT_ENDPOINT": "https://leoyao-agent-eastus2-resource.services.ai.azure.com/api/projects/leoyao-agent-eastus2", - "MODEL_DEPLOYMENT_NAME": "gpt-5.2" -} diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/dotnetmultiagent.csproj b/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/dotnetmultiagent.csproj deleted file mode 100644 index d884ae2b5e..0000000000 --- a/dotnet/samples/05-end-to-end/HostedAgents/foundry_multiagent/dotnetmultiagent.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - Exe - net9.0 - enable - enable - - - - - - - - - - - - - - - - - - PreserveNewest - - - diff --git a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/dotnetsingle.csproj b/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/dotnetsingle.csproj deleted file mode 100644 index d714c09052..0000000000 --- a/dotnet/samples/05-end-to-end/HostedAgents/foundry_single_agent/dotnetsingle.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - Exe - net10.0 - enable - enable - true - - - - - - - - - diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml index 9246218e02..bb854430bc 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml +++ b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml @@ -1,24 +1,31 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml -kind: hosted -name: python-multiagent +name: foundry-multiagent +displayName: "Foundry Multi-Agent Workflow" description: > A multi-agent workflow featuring a Writer and Reviewer that collaborate - to create and refine content. + to create and refine content using Azure AI Foundry. metadata: authors: - - Microsoft + - Microsoft Agent Framework Team tags: - Azure AI AgentServer - Microsoft Agent Framework - Multi-Agent Workflow - Writer-Reviewer - Content Creation -protocols: - - protocol: responses - version: v1 -environment_variables: - - name: PROJECT_ENDPOINT - value: "{{PROJECT_ENDPOINT}}" - - name: MODEL_DEPLOYMENT_NAME - value: "{{MODEL_DEPLOYMENT_NAME}}" +template: + kind: hosted + name: foundry-multiagent + protocols: + - protocol: responses + version: v1 + environment_variables: + - name: PROJECT_ENDPOINT + value: ${PROJECT_ENDPOINT} + - name: MODEL_DEPLOYMENT_NAME + value: gpt-4o-mini +resources: + - name: "gpt-4o-mini" + kind: model + id: gpt-4o-mini diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py index 63658879f1..fc8d20cc54 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py +++ b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py @@ -100,7 +100,7 @@ async def main() -> None: print("Starting workflow agent HTTP server...") from azure.ai.agentserver.agentframework import from_agent_framework - await from_agent_framework(agent).run_async() + await from_agent_framework(agent).run_async() if __name__ == "__main__": diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt index e2e7cd2f65..3cc5eab643 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt +++ b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt @@ -1,4 +1,2 @@ azure-ai-agentserver-agentframework==1.0.0b14 -debugpy -# Agent development CLI tool (preview) -agent-dev-cli \ No newline at end of file +agent-framework \ No newline at end of file diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml index 9967f88ff1..69c6ea94a9 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml @@ -1,25 +1,32 @@ # yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml -kind: hosted -name: python-single +name: foundry-single-agent +displayName: "Foundry Single Agent with Local Tools" description: > A travel assistant agent that helps users find hotels in Seattle. Demonstrates local Python tool execution - a key advantage of code-based hosted agents over prompt agents. metadata: authors: - - Microsoft + - Microsoft Agent Framework Team tags: - Azure AI AgentServer - Microsoft Agent Framework - Local Tools - Travel Assistant - Hotel Search -protocols: - - protocol: responses - version: v1 -environment_variables: - - name: PROJECT_ENDPOINT - value: "{{PROJECT_ENDPOINT}}" - - name: MODEL_DEPLOYMENT_NAME - value: "{{MODEL_DEPLOYMENT_NAME}}" \ No newline at end of file +template: + kind: hosted + name: foundry-single-agent + protocols: + - protocol: responses + version: v1 + environment_variables: + - name: PROJECT_ENDPOINT + value: ${PROJECT_ENDPOINT} + - name: MODEL_DEPLOYMENT_NAME + value: gpt-4o-mini +resources: + - name: "gpt-4o-mini" + kind: model + id: gpt-4o-mini \ No newline at end of file diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt index e2e7cd2f65..3cc5eab643 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt @@ -1,4 +1,2 @@ azure-ai-agentserver-agentframework==1.0.0b14 -debugpy -# Agent development CLI tool (preview) -agent-dev-cli \ No newline at end of file +agent-framework \ No newline at end of file From 4cd33cd0520cf80e48d79d4f7cb3e279fc019bd1 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Fri, 27 Feb 2026 20:07:29 +0000 Subject: [PATCH 03/14] Align foundry samples: fix builds, upgrade AgentServer to beta.8 - Fix TargetFrameworks (plural) to override inherited net472 from Directory.Build.props - Upgrade Azure.AI.AgentServer.AgentFramework to 1.0.0-beta.8 (latest) - Bump OpenTelemetry packages to 1.12.0 (required by beta.8) - Fix Roslynator/format errors (imports ordering, BOM, sealed record, target-typed new) - Verified with docker dotnet format (matching CI pipeline) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../FoundryMultiAgent/FoundryMultiAgent.csproj | 8 ++++---- .../FoundrySingleAgent/FoundrySingleAgent.csproj | 4 ++-- .../HostedAgents/FoundrySingleAgent/Program.cs | 13 +++++++------ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj index 45d3bd8be0..4080cbce98 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj @@ -1,7 +1,7 @@  Exe - net10.0 + net10.0 enable enable @@ -33,15 +33,15 @@ - + - - + + diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj index 89b952be32..bf3b107c33 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj @@ -1,7 +1,7 @@ Exe - net10.0 + net10.0 enable enable @@ -33,7 +33,7 @@ - + diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs index 64465e6f34..09bf992d8b 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs @@ -1,13 +1,14 @@ -// Copyright (c) Microsoft. All rights reserved. +// Copyright (c) Microsoft. All rights reserved. // Seattle Hotel Agent - A simple agent with a tool to find hotels in Seattle. // Uses Microsoft Agent Framework with Azure AI Foundry. // Ready for deployment to Foundry Hosted Agent service. +using System.ClientModel.Primitives; using System.ComponentModel; using System.Globalization; using System.Text; -using System.ClientModel.Primitives; + using Azure.AI.AgentServer.AgentFramework.Extensions; using Azure.AI.OpenAI; using Azure.AI.Projects; @@ -43,12 +44,12 @@ string GetAvailableHotels( // Parse dates if (!DateTime.TryParseExact(checkInDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var checkIn)) { - return $"Error parsing check-in date. Please use YYYY-MM-DD format."; + return "Error parsing check-in date. Please use YYYY-MM-DD format."; } if (!DateTime.TryParseExact(checkOutDate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var checkOut)) { - return $"Error parsing check-out date. Please use YYYY-MM-DD format."; + return "Error parsing check-out date. Please use YYYY-MM-DD format."; } // Validate dates @@ -92,7 +93,7 @@ string GetAvailableHotels( // Create chat client using AIProjectClient to get the OpenAI connection from the project var credential = new DefaultAzureCredential(); -AIProjectClient projectClient = new AIProjectClient(new Uri(endpoint), credential); +AIProjectClient projectClient = new(new Uri(endpoint), credential); // Get the OpenAI connection from the project ClientConnection connection = projectClient.GetConnection(typeof(AzureOpenAIClient).FullName!); @@ -135,4 +136,4 @@ politely let them know you specialize in Seattle hotel recommendations. await agent.RunAIAgentAsync(telemetrySourceName: "Agents"); // Hotel record for simulated data -record Hotel(string Name, int PricePerNight, double Rating, string Location); +internal sealed record Hotel(string Name, int PricePerNight, double Rating, string Location); From f2ba7093c70989555f9f7dae2f446829774fc559 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Fri, 27 Feb 2026 21:36:02 +0000 Subject: [PATCH 04/14] Refactor hosted samples to use AIProjectClient.CreateAIAgentAsync Replace PersistentAgentsClient and manual AzureOpenAIClient setup with AIProjectClient.CreateAIAgentAsync() from Microsoft.Agents.AI.AzureAI. - FoundryMultiAgent: Remove Azure.AI.Agents.Persistent, use CreateAIAgentAsync for Writer and Reviewer agents with cleanup in finally block - FoundrySingleAgent: Remove manual GetConnection/AzureOpenAIClient chain, use CreateAIAgentAsync with hotel search tool - Update csproj: add Microsoft.Agents.AI.AzureAI, remove unused packages Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../FoundryMultiAgent.csproj | 3 +- .../HostedAgents/FoundryMultiAgent/Program.cs | 87 ++++--------------- .../FoundrySingleAgent.csproj | 4 +- .../FoundrySingleAgent/Program.cs | 47 ++++------ 4 files changed, 38 insertions(+), 103 deletions(-) diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj index 4080cbce98..b2fb41ac5e 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj @@ -34,12 +34,11 @@ - + - diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs index 5ded21282a..7c393ff125 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs @@ -1,15 +1,13 @@ // Copyright (c) Microsoft. All rights reserved. // This sample demonstrates a multi-agent workflow with Writer and Reviewer agents -// using Azure AI Foundry PersistentAgentsClient and the Agent Framework WorkflowBuilder. +// using Azure AI Foundry AIProjectClient and the Agent Framework WorkflowBuilder. -using Azure.AI.Agents.Persistent; using Azure.AI.AgentServer.AgentFramework.Extensions; -using Azure.Core; +using Azure.AI.Projects; using Azure.Identity; using Microsoft.Agents.AI; using Microsoft.Agents.AI.Workflows; -using Microsoft.Extensions.AI; var endpoint = Environment.GetEnvironmentVariable("PROJECT_ENDPOINT") ?? throw new InvalidOperationException("PROJECT_ENDPOINT is not set."); @@ -21,36 +19,23 @@ // WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production. // In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid // latency issues, unintended credential probing, and potential security risks from fallback mechanisms. -TokenCredential credential = string.IsNullOrEmpty(Environment.GetEnvironmentVariable("MSI_ENDPOINT")) - ? new DefaultAzureCredential() - : new ManagedIdentityCredential(); +AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential()); -// Create separate PersistentAgentsClient for each agent -var writerClient = new PersistentAgentsClient(endpoint, credential); -var reviewerClient = new PersistentAgentsClient(endpoint, credential); +// Create Foundry agents +AIAgent writerAgent = await aiProjectClient.CreateAIAgentAsync( + name: "Writer", + model: deploymentName, + instructions: "You are an excellent content writer. You create new content and edit contents based on the feedback."); -(ChatClientAgent agent, string id)? writer = null; -(ChatClientAgent agent, string id)? reviewer = null; +AIAgent reviewerAgent = await aiProjectClient.CreateAIAgentAsync( + name: "Reviewer", + model: deploymentName, + instructions: "You are an excellent content reviewer. Provide actionable feedback to the writer about the provided content. Provide the feedback in the most concise manner possible."); try { - // Create Foundry agents with separate clients - writer = await CreateAgentAsync( - writerClient, - deploymentName, - "Writer", - "You are an excellent content writer. You create new content and edit contents based on the feedback." - ); - reviewer = await CreateAgentAsync( - reviewerClient, - deploymentName, - "Reviewer", - "You are an excellent content reviewer. Provide actionable feedback to the writer about the provided content. Provide the feedback in the most concise manner possible." - ); - - var workflow = new WorkflowBuilder(writer.Value.agent) - .AddEdge(writer.Value.agent, reviewer.Value.agent) - .WithOutputFrom(reviewer.Value.agent) + var workflow = new WorkflowBuilder(writerAgent) + .AddEdge(writerAgent, reviewerAgent) .Build(); Console.WriteLine("Starting Writer-Reviewer Workflow Agent Server on http://localhost:8088"); @@ -58,45 +43,7 @@ } finally { - // Clean up all resources - await CleanupAsync(writerClient, writer?.id); - await CleanupAsync(reviewerClient, reviewer?.id); - - if (credential is IDisposable disposable) - { - disposable.Dispose(); - } -} - -static async Task<(ChatClientAgent agent, string id)> CreateAgentAsync( - PersistentAgentsClient client, - string model, - string name, - string instructions) -{ - var agentMetadata = await client.Administration.CreateAgentAsync( - model: model, - name: name, - instructions: instructions - ); - - var chatClient = client.AsIChatClient(agentMetadata.Value.Id); - return (new ChatClientAgent(chatClient), agentMetadata.Value.Id); -} - -static async Task CleanupAsync(PersistentAgentsClient client, string? agentId) -{ - if (string.IsNullOrEmpty(agentId)) - { - return; - } - - try - { - await client.Administration.DeleteAgentAsync(agentId); - } - catch (Exception e) - { - Console.WriteLine($"Cleanup failed for agent {agentId}: {e.Message}"); - } + // Cleanup server-side agents + await aiProjectClient.Agents.DeleteAgentAsync(writerAgent.Name); + await aiProjectClient.Agents.DeleteAgentAsync(reviewerAgent.Name); } diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj index bf3b107c33..756f3d30ee 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj @@ -35,9 +35,9 @@ - - + + diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs index 09bf992d8b..d8e323bf8f 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs @@ -4,13 +4,11 @@ // Uses Microsoft Agent Framework with Azure AI Foundry. // Ready for deployment to Foundry Hosted Agent service. -using System.ClientModel.Primitives; using System.ComponentModel; using System.Globalization; using System.Text; using Azure.AI.AgentServer.AgentFramework.Extensions; -using Azure.AI.OpenAI; using Azure.AI.Projects; using Azure.Identity; using Microsoft.Agents.AI; @@ -91,29 +89,15 @@ string GetAvailableHotels( } } -// Create chat client using AIProjectClient to get the OpenAI connection from the project -var credential = new DefaultAzureCredential(); -AIProjectClient projectClient = new(new Uri(endpoint), credential); +// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production. +// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid +// latency issues, unintended credential probing, and potential security risks from fallback mechanisms. +AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential()); -// Get the OpenAI connection from the project -ClientConnection connection = projectClient.GetConnection(typeof(AzureOpenAIClient).FullName!); - -if (!connection.TryGetLocatorAsUri(out Uri? openAiEndpoint) || openAiEndpoint is null) -{ - throw new InvalidOperationException("Failed to get OpenAI endpoint from project connection."); -} -openAiEndpoint = new Uri($"https://{openAiEndpoint.Host}"); -Console.WriteLine($"OpenAI Endpoint: {openAiEndpoint}"); - -var chatClient = new AzureOpenAIClient(openAiEndpoint, credential) - .GetChatClient(deploymentName) - .AsIChatClient() - .AsBuilder() - .UseOpenTelemetry(sourceName: "Agents", configure: cfg => cfg.EnableSensitiveData = false) - .Build(); - -var agent = new ChatClientAgent(chatClient, +// Create Foundry agent with hotel search tool +AIAgent agent = await aiProjectClient.CreateAIAgentAsync( name: "SeattleHotelAgent", + model: deploymentName, instructions: """ You are a helpful travel assistant specializing in finding hotels in Seattle, Washington. @@ -127,13 +111,18 @@ 5. Offer to help with additional questions about the hotels or Seattle Be conversational and helpful. If users ask about things outside of Seattle hotels, politely let them know you specialize in Seattle hotel recommendations. """, - tools: [AIFunctionFactory.Create(GetAvailableHotels)]) - .AsBuilder() - .UseOpenTelemetry(sourceName: "Agents", configure: cfg => cfg.EnableSensitiveData = false) - .Build(); + tools: [AIFunctionFactory.Create(GetAvailableHotels)]); -Console.WriteLine("Seattle Hotel Agent Server running on http://localhost:8088"); -await agent.RunAIAgentAsync(telemetrySourceName: "Agents"); +try +{ + Console.WriteLine("Seattle Hotel Agent Server running on http://localhost:8088"); + await agent.RunAIAgentAsync(telemetrySourceName: "Agents"); +} +finally +{ + // Cleanup server-side agent + await aiProjectClient.Agents.DeleteAgentAsync(agent.Name); +} // Hotel record for simulated data internal sealed record Hotel(string Name, int PricePerNight, double Rating, string Location); From 7302b3d72b883ac7eca73983eb92e79a3da4cfbb Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Fri, 27 Feb 2026 21:37:03 +0000 Subject: [PATCH 05/14] Update READMEs to reflect AIProjectClient.CreateAIAgentAsync usage - Reference Microsoft.Agents.AI.AzureAI and Microsoft.Agents.AI.Workflows packages - Add Azure AI Developer role requirement for agents/write data action - Replace PersistentAgentsClient references Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../05-end-to-end/HostedAgents/FoundryMultiAgent/README.md | 5 +++-- .../05-end-to-end/HostedAgents/FoundrySingleAgent/README.md | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md index e9f35757e1..6b71326e9d 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md @@ -20,12 +20,12 @@ The agent is hosted using the [Azure AI AgentServer SDK](https://www.nuget.org/p ### Multi-Agent Workflow -In [Program.cs](Program.cs), the sample creates two agents using `PersistentAgentsClient`: +In [Program.cs](Program.cs), the sample creates two agents using `AIProjectClient.CreateAIAgentAsync()` from the [Microsoft.Agents.AI.AzureAI](https://www.nuget.org/packages/Microsoft.Agents.AI.AzureAI/) package: - **Writer** - An agent that creates and edits content based on feedback - **Reviewer** - An agent that provides actionable feedback on the content -The `WorkflowBuilder` connects these agents in a sequential flow: +The `WorkflowBuilder` from the [Microsoft.Agents.AI.Workflows](https://www.nuget.org/packages/Microsoft.Agents.AI.Workflows/) package connects these agents in a sequential flow: 1. The Writer receives the initial request and generates content 2. The Reviewer evaluates the content and provides feedback @@ -51,6 +51,7 @@ Before running this sample, ensure you have: 2. **Azure CLI** - Installed and authenticated - Run `az login` and verify with `az account show` + - Your identity needs the **Azure AI Developer** role on the Foundry resource (for `agents/write` data action required by `CreateAIAgentAsync`) 3. **.NET 10.0 SDK or later** - Verify your version: `dotnet --version` diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/README.md b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/README.md index 4039a846d7..04dbca86d0 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/README.md +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/README.md @@ -20,7 +20,7 @@ The agent is hosted using the [Azure AI AgentServer SDK](https://learn.microsoft ### Local Tools Integration -In [Program.cs](Program.cs), the agent uses a local C# method (`GetAvailableHotels`) that simulates a hotel availability API. This demonstrates how code-based agents can execute custom server-side logic that prompt agents cannot access. +In [Program.cs](Program.cs), the agent uses `AIProjectClient.CreateAIAgentAsync()` from the [Microsoft.Agents.AI.AzureAI](https://www.nuget.org/packages/Microsoft.Agents.AI.AzureAI/) package to create a Foundry agent with a local C# method (`GetAvailableHotels`) that simulates a hotel availability API. This demonstrates how code-based agents can execute custom server-side logic that prompt agents cannot access. The tool accepts: @@ -47,6 +47,7 @@ Before running this sample, ensure you have: 2. **Azure CLI** - Installed and authenticated - Run `az login` and verify with `az account show` + - Your identity needs the **Azure AI Developer** role on the Foundry resource (for `agents/write` data action required by `CreateAIAgentAsync`) 3. **.NET 10.0 SDK or later** - Verify your version: `dotnet --version` From fc4b6dbedbd3b3b279916b08fefc569152dbcc29 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Fri, 27 Feb 2026 21:38:46 +0000 Subject: [PATCH 06/14] Add HostedAgents READMEs and Foundry samples to solution - Create dotnet/samples/05-end-to-end/HostedAgents/README.md with sample index - Create python/samples/05-end-to-end/hosted_agents/README.md with sample index - Add FoundryMultiAgent and FoundrySingleAgent to agent-framework-dotnet.slnx Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/agent-framework-dotnet.slnx | 2 ++ .../05-end-to-end/HostedAgents/README.md | 22 +++++++++++++++++++ .../05-end-to-end/hosted_agents/README.md | 21 ++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 dotnet/samples/05-end-to-end/HostedAgents/README.md create mode 100644 python/samples/05-end-to-end/hosted_agents/README.md diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx index 1ab73c2b8b..a1cc20a5ad 100644 --- a/dotnet/agent-framework-dotnet.slnx +++ b/dotnet/agent-framework-dotnet.slnx @@ -287,6 +287,8 @@ + + diff --git a/dotnet/samples/05-end-to-end/HostedAgents/README.md b/dotnet/samples/05-end-to-end/HostedAgents/README.md new file mode 100644 index 0000000000..226fd07100 --- /dev/null +++ b/dotnet/samples/05-end-to-end/HostedAgents/README.md @@ -0,0 +1,22 @@ +# Hosted Agent Samples + +These samples demonstrate how to build and deploy **code-based hosted agents** using the [Azure AI AgentServer SDK](https://www.nuget.org/packages/Azure.AI.AgentServer.AgentFramework/). Each sample can run locally and be deployed to Microsoft Foundry. + +## Samples + +| Sample | Description | +|--------|-------------| +| [`AgentsInWorkflows`](./AgentsInWorkflows/) | Translation workflow with 3 sequential agents (French → Spanish → English) using `WorkflowBuilder` | +| [`AgentWithHostedMCP`](./AgentWithHostedMCP/) | Agent with Hosted MCP server integration for Microsoft Learn documentation search | +| [`AgentWithTextSearchRag`](./AgentWithTextSearchRag/) | RAG pattern using `TextSearchProvider` for pre-invocation document search with source citations | +| [`FoundryMultiAgent`](./FoundryMultiAgent/) | Multi-agent Writer-Reviewer workflow using `AIProjectClient.CreateAIAgentAsync()` from [Microsoft.Agents.AI.AzureAI](https://www.nuget.org/packages/Microsoft.Agents.AI.AzureAI/) | +| [`FoundrySingleAgent`](./FoundrySingleAgent/) | Single agent with local C# tool execution (hotel search) using `AIProjectClient.CreateAIAgentAsync()` from [Microsoft.Agents.AI.AzureAI](https://www.nuget.org/packages/Microsoft.Agents.AI.AzureAI/) | + +## Prerequisites + +- .NET 10.0 SDK or later +- Azure AI Foundry Project with a deployed chat model +- Azure CLI (`az login`) +- **Azure AI Developer** role on the Foundry resource (for samples using `CreateAIAgentAsync`) + +See each sample's README for specific setup instructions. diff --git a/python/samples/05-end-to-end/hosted_agents/README.md b/python/samples/05-end-to-end/hosted_agents/README.md new file mode 100644 index 0000000000..88ef861d2e --- /dev/null +++ b/python/samples/05-end-to-end/hosted_agents/README.md @@ -0,0 +1,21 @@ +# Hosted Agent Samples + +These samples demonstrate how to build and deploy **code-based hosted agents** using the [Azure AI AgentServer SDK](https://pypi.org/project/azure-ai-agentserver-agentframework/). Each sample can run locally and be deployed to Microsoft Foundry. + +## Samples + +| Sample | Description | +|--------|-------------| +| [`agents_in_workflow`](./agents_in_workflow/) | Translation workflow with 3 sequential agents (French → Spanish → English) | +| [`agent_with_hosted_mcp`](./agent_with_hosted_mcp/) | Agent with Hosted MCP server integration for Microsoft Learn documentation search | +| [`agent_with_text_search_rag`](./agent_with_text_search_rag/) | RAG pattern with text search for pre-invocation document retrieval | +| [`foundry_multiagent`](./foundry_multiagent/) | Multi-agent Writer-Reviewer workflow using Azure AI Foundry agents | +| [`foundry_single_agent`](./foundry_single_agent/) | Single agent with local tool execution (hotel search) using Azure AI Foundry | + +## Prerequisites + +- Python 3.10 or later +- Azure AI Foundry Project with a deployed chat model +- Azure CLI (`az login`) + +See each sample's README for specific setup instructions. From 986a6011ec3e2df456115b844d957efd85c5136f Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Fri, 27 Feb 2026 23:03:45 +0000 Subject: [PATCH 07/14] Fix Python linting: reorder imports before load_dotenv, remove trailing whitespace Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../hosted_agents/foundry_single_agent/main.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py index 19acbddcde..38fba192e4 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py @@ -9,13 +9,12 @@ from datetime import datetime from typing import Annotated -from dotenv import load_dotenv - -load_dotenv(override=True) - from agent_framework.azure import AzureAIAgentClient from azure.ai.agentserver.agentframework import from_agent_framework from azure.identity.aio import DefaultAzureCredential +from dotenv import load_dotenv + +load_dotenv(override=True) # Configure these for your Foundry project # Read the explicit variables present in the .env file @@ -135,7 +134,7 @@ async def main(): 4. Present the results in a friendly, informative way 5. Offer to help with additional questions about the hotels or Seattle -Be conversational and helpful. If users ask about things outside of Seattle hotels, +Be conversational and helpful. If users ask about things outside of Seattle hotels, politely let them know you specialize in Seattle hotel recommendations.""", tools=[get_available_hotels], ) From 6ccc87f218704c8b789edf5ceb11a38686fe1d4e Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Fri, 27 Feb 2026 23:20:10 +0000 Subject: [PATCH 08/14] Update uv.lock to match latest package versions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- python/uv.lock | 395 ++++++++++++++++++++++++++----------------------- 1 file changed, 208 insertions(+), 187 deletions(-) diff --git a/python/uv.lock b/python/uv.lock index 9f2e97a91e..328ac6f577 100644 --- a/python/uv.lock +++ b/python/uv.lock @@ -508,7 +508,8 @@ version = "1.0.0b260225" source = { editable = "packages/github_copilot" } dependencies = [ { name = "agent-framework-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "github-copilot-sdk", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "github-copilot-sdk", version = "0.1.25", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "github-copilot-sdk", version = "0.1.29", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, ] [package.metadata] @@ -888,7 +889,7 @@ wheels = [ [[package]] name = "anthropic" -version = "0.83.0" +version = "0.84.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -900,9 +901,9 @@ dependencies = [ { name = "sniffio", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/db/e5/02cd2919ec327b24234abb73082e6ab84c451182cc3cc60681af700f4c63/anthropic-0.83.0.tar.gz", hash = "sha256:a8732c68b41869266c3034541a31a29d8be0f8cd0a714f9edce3128b351eceb4", size = 534058, upload-time = "2026-02-19T19:26:38.904Z" } +sdist = { url = "https://files.pythonhosted.org/packages/04/ea/0869d6df9ef83dcf393aeefc12dd81677d091c6ffc86f783e51cf44062f2/anthropic-0.84.0.tar.gz", hash = "sha256:72f5f90e5aebe62dca316cb013629cfa24996b0f5a4593b8c3d712bc03c43c37", size = 539457, upload-time = "2026-02-25T05:22:38.54Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/75/b9d58e4e2a4b1fc3e75ffbab978f999baf8b7c4ba9f96e60edb918ba386b/anthropic-0.83.0-py3-none-any.whl", hash = "sha256:f069ef508c73b8f9152e8850830d92bd5ef185645dbacf234bb213344a274810", size = 456991, upload-time = "2026-02-19T19:26:40.114Z" }, + { url = "https://files.pythonhosted.org/packages/64/ca/218fa25002a332c0aa149ba18ffc0543175998b1f65de63f6d106689a345/anthropic-0.84.0-py3-none-any.whl", hash = "sha256:861c4c50f91ca45f942e091d83b60530ad6d4f98733bfe648065364da05d29e7", size = 455156, upload-time = "2026-02-25T05:22:40.468Z" }, ] [[package]] @@ -1166,11 +1167,11 @@ wheels = [ [[package]] name = "certifi" -version = "2026.1.4" +version = "2026.2.25" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" } +sdist = { url = "https://files.pythonhosted.org/packages/af/2d/7bf41579a8986e348fa033a31cdd0e4121114f6bce2457e8876010b092dd/certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7", size = 155029, upload-time = "2026-02-25T02:54:17.342Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" }, + { url = "https://files.pythonhosted.org/packages/9a/3c/c17fb3ca2d9c3acff52e30b309f538586f9f5b9c9cf454f3845fc9af4881/certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa", size = 153684, upload-time = "2026-02-25T02:54:15.766Z" }, ] [[package]] @@ -1346,19 +1347,19 @@ wheels = [ [[package]] name = "claude-agent-sdk" -version = "0.1.41" +version = "0.1.44" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "mcp", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b8/f9/4dfd1cfaa7271956bb86e73259c3a87fc032a03c28333db20aefde8706ab/claude_agent_sdk-0.1.41.tar.gz", hash = "sha256:b2b56875fe9b7b389406b53c9020794caf0a29f2b3597b2eca78a61800f9a914", size = 62440, upload-time = "2026-02-24T06:56:09.223Z" } +sdist = { url = "https://files.pythonhosted.org/packages/30/40/5661e10daf69ee5c864f82a1888cc33c9378b2d7f7d11db3c2360aef3a30/claude_agent_sdk-0.1.44.tar.gz", hash = "sha256:8629436e7af367a1cbc81aa2a58a93aa68b8b2e4e14b0c5be5ac3627bd462c1b", size = 62439, upload-time = "2026-02-26T01:17:28.118Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/9b/ebb88bb665c2dfea9c21690f56a4397d647be3ed911de173e2f12c2d69ca/claude_agent_sdk-0.1.41-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4484149ac440393a904306016bf2fffec5d2d5a76e6c559d18f3e25699f5ec87", size = 55601983, upload-time = "2026-02-24T06:55:55.695Z" }, - { url = "https://files.pythonhosted.org/packages/f8/33/e5a85efaa716be0325a581446c3f85805719383fff206ca0da54c0d84783/claude_agent_sdk-0.1.41-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:d155772d607f1cffbee6ac6018834aee090e98b2d3a8db52be6302b768e354a7", size = 70326675, upload-time = "2026-02-24T06:55:59.486Z" }, - { url = "https://files.pythonhosted.org/packages/00/f4/52e62853898766b83575e06bfaee1e6306b31a07a3171dc1dfec2738ce5c/claude_agent_sdk-0.1.41-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:24a48725cb764443861bf4eb17af1f6a323c72b39fe1a7d703bf29f744c64ad1", size = 70923548, upload-time = "2026-02-24T06:56:02.776Z" }, - { url = "https://files.pythonhosted.org/packages/75/f9/584dd08c0ea9af2c0b9ba406dad819a167b757ef8d23db8135ba4a7b177f/claude_agent_sdk-0.1.41-py3-none-win_amd64.whl", hash = "sha256:bca68993c0d2663f6046eff9ac26a03fbc4fd0eba210ab8a4a76fb00930cb8a1", size = 73259355, upload-time = "2026-02-24T06:56:06.295Z" }, + { url = "https://files.pythonhosted.org/packages/e9/1a/dcde83a6477bfdf8c5510fd84006cca763296e6bc5576e90cd89b97ec034/claude_agent_sdk-0.1.44-py3-none-macosx_11_0_arm64.whl", hash = "sha256:1dd976ad3efb673aefd5037dc75ee7926fb5033c4b9ab7382897ab647fed74e6", size = 55828889, upload-time = "2026-02-26T01:17:15.474Z" }, + { url = "https://files.pythonhosted.org/packages/4b/33/3b161256956968e18c81e2b2650fed7d2a1144d51042ed6317848643e5d7/claude_agent_sdk-0.1.44-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:d35b38ca40fa28f50fa88705599a298ab30c121c56b53655025eeceb463ac399", size = 70795212, upload-time = "2026-02-26T01:17:18.873Z" }, + { url = "https://files.pythonhosted.org/packages/17/cb/67af9796dad77a94dfe851138f5ffc9e2e0a14407ba55fea07462c1cc8e5/claude_agent_sdk-0.1.44-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:853c15501f71a913a6cc6b40dc0b24b9505166cad164206b8eab229889e670b8", size = 71424685, upload-time = "2026-02-26T01:17:22.345Z" }, + { url = "https://files.pythonhosted.org/packages/46/cd/2d3806c791250a76de2c1be863fc01d420729ad61496253e3d3033464c72/claude_agent_sdk-0.1.44-py3-none-win_amd64.whl", hash = "sha256:597e2fcad372086f93e4f6a380d3088ec4dd9b9efce309c5281b52a256fd5d25", size = 73493771, upload-time = "2026-02-26T01:17:25.837Z" }, ] [[package]] @@ -1378,7 +1379,7 @@ name = "clr-loader" version = "0.2.10" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cffi", marker = "(python_full_version < '3.14' and sys_platform == 'darwin') or (python_full_version < '3.14' and sys_platform == 'linux') or (python_full_version < '3.14' and sys_platform == 'win32')" }, + { name = "cffi", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/18/24/c12faf3f61614b3131b5c98d3bf0d376b49c7feaa73edca559aeb2aee080/clr_loader-0.2.10.tar.gz", hash = "sha256:81f114afbc5005bafc5efe5af1341d400e22137e275b042a8979f3feb9fc9446", size = 83605, upload-time = "2026-01-03T23:13:06.984Z" } wheels = [ @@ -1817,7 +1818,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "asyncio", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "grpcio", version = "1.67.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.14' and sys_platform == 'darwin') or (python_full_version < '3.14' and sys_platform == 'linux') or (python_full_version < '3.14' and sys_platform == 'win32')" }, - { name = "grpcio", version = "1.78.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.14' and sys_platform == 'darwin') or (python_full_version >= '3.14' and sys_platform == 'linux') or (python_full_version >= '3.14' and sys_platform == 'win32')" }, + { name = "grpcio", version = "1.78.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.14' and sys_platform == 'darwin') or (python_full_version >= '3.14' and sys_platform == 'linux') or (python_full_version >= '3.14' and sys_platform == 'win32')" }, { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "protobuf", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] @@ -1857,7 +1858,7 @@ name = "exceptiongroup" version = "1.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(python_full_version < '3.13' and sys_platform == 'darwin') or (python_full_version < '3.13' and sys_platform == 'linux') or (python_full_version < '3.13' and sys_platform == 'win32')" }, ] sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } wheels = [ @@ -1875,7 +1876,7 @@ wheels = [ [[package]] name = "fastapi" -version = "0.133.0" +version = "0.134.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -1884,9 +1885,9 @@ dependencies = [ { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "typing-inspection", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c2/04/ab382c7c03dd545f2c964d06e87ad0d5faa944a2434186ad9c285f5d87e0/fastapi-0.133.0.tar.gz", hash = "sha256:b900a2bf5685cdb0647a41d5900bdeafc3a9e8a28ac08c6246b76699e164d60d", size = 373265, upload-time = "2026-02-24T09:53:40.143Z" } +sdist = { url = "https://files.pythonhosted.org/packages/96/15/647ea81cb73b55b48fb095158a9cd64e42e9e4f1d34dbb5cc4a4939779d6/fastapi-0.134.0.tar.gz", hash = "sha256:3122b1ea0dbeaab48b5976e80b99ca7eda02be154bf03e126a33220e73255a9a", size = 385667, upload-time = "2026-02-27T21:18:12.931Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/b4/023e75a2ec3f5440e380df6caf4d28edc0806d007193e6fb0707237886a4/fastapi-0.133.0-py3-none-any.whl", hash = "sha256:0a78878483d60702a1dde864c24ab349a1a53ef4db6b6f74f8cd4a2b2bc67d2f", size = 104787, upload-time = "2026-02-24T09:53:41.404Z" }, + { url = "https://files.pythonhosted.org/packages/e3/e6/fd49c28a54b7d6f5c64045155e40f6cff9ed4920055043fb5ac7969f7f2f/fastapi-0.134.0-py3-none-any.whl", hash = "sha256:f4e7214f24b2262258492e05c48cf21125e4ffc427e30dd32fb4f74049a3d56a", size = 110404, upload-time = "2026-02-27T21:18:10.809Z" }, ] [[package]] @@ -2249,10 +2250,15 @@ wheels = [ name = "github-copilot-sdk" version = "0.1.25" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11' and sys_platform == 'darwin'", + "python_full_version < '3.11' and sys_platform == 'linux'", + "python_full_version < '3.11' and sys_platform == 'win32'", +] dependencies = [ - { name = "pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "python-dateutil", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "pydantic", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "python-dateutil", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, + { name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] wheels = [ { url = "https://files.pythonhosted.org/packages/87/06/1dec504b54c724d69283969d4ed004225ec8bbb1c0a5e9e0c3b6b048099a/github_copilot_sdk-0.1.25-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:d32c3fc2c393f70923a645a133607da2e562d078b87437f499100d5bb8c1902f", size = 58097936, upload-time = "2026-02-18T00:07:20.672Z" }, @@ -2263,6 +2269,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6b/2e/4cffd33552ede91de7517641835a3365571abd3f436c9d76a4f50793033c/github_copilot_sdk-0.1.25-py3-none-win_arm64.whl", hash = "sha256:5249a63d1ac1e4d325c70c9902e81327b0baca53afa46010f52ac3fd3b5a111b", size = 51623455, upload-time = "2026-02-18T00:07:42.156Z" }, ] +[[package]] +name = "github-copilot-sdk" +version = "0.1.29" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.14' and sys_platform == 'darwin'", + "python_full_version == '3.13.*' and sys_platform == 'darwin'", + "python_full_version == '3.12.*' and sys_platform == 'darwin'", + "python_full_version == '3.11.*' and sys_platform == 'darwin'", + "python_full_version >= '3.14' and sys_platform == 'linux'", + "python_full_version == '3.13.*' and sys_platform == 'linux'", + "python_full_version == '3.12.*' and sys_platform == 'linux'", + "python_full_version == '3.11.*' and sys_platform == 'linux'", + "python_full_version >= '3.14' and sys_platform == 'win32'", + "python_full_version == '3.13.*' and sys_platform == 'win32'", + "python_full_version == '3.12.*' and sys_platform == 'win32'", + "python_full_version == '3.11.*' and sys_platform == 'win32'", +] +dependencies = [ + { name = "pydantic", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, + { name = "python-dateutil", marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/8e/2155e40594a60084266d33cefd2333fe3ce44e7189773e6eff9943e25d81/github_copilot_sdk-0.1.29-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:0215045cf6ec2cebfc6dbb0e257e2116d4aa05751f80cc48d5f3c8c658933094", size = 58182462, upload-time = "2026-02-27T22:09:59.687Z" }, + { url = "https://files.pythonhosted.org/packages/55/6a/9fa577564702eb1eb143c16afcdadf7d6305da53fbbd05a0925035808d9e/github_copilot_sdk-0.1.29-py3-none-macosx_11_0_arm64.whl", hash = "sha256:441c917aad8501da5264026b0da5c0e834571256e812617437654ab16bdad77f", size = 54934772, upload-time = "2026-02-27T22:10:02.911Z" }, + { url = "https://files.pythonhosted.org/packages/69/77/0e0fd6f6a0177d93f5f3e5d0e9ed5044fc53c54e58e65bbc6b08eb789350/github_copilot_sdk-0.1.29-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:88230b779dee1695fc44043060006224138c5b5d6724890f7ecdc378ff0d8f73", size = 61071028, upload-time = "2026-02-27T22:10:06.332Z" }, + { url = "https://files.pythonhosted.org/packages/94/f5/9a73bd6e34db4d0ce546b04725cfad1c9fa58426265876b640376381b623/github_copilot_sdk-0.1.29-py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:2019bbbaea39d8db54250d11431d89952dd0ad0a16b58159b6b018ea625c78c9", size = 59251702, upload-time = "2026-02-27T22:10:09.466Z" }, + { url = "https://files.pythonhosted.org/packages/ea/32/60713b1ae3ed80b62113f993bd2f4552d2b03753cfea37f90086ac8e6d6e/github_copilot_sdk-0.1.29-py3-none-win_amd64.whl", hash = "sha256:a326fe5ab6ecd7cef5de39d5a5fe18e09e629eb29b401be23a709e83fc578578", size = 53690857, upload-time = "2026-02-27T22:10:12.778Z" }, + { url = "https://files.pythonhosted.org/packages/58/31/d082f4ac13cf3e4ba3a7846b8468521d6d38967de3788a61b6001707fbb5/github_copilot_sdk-0.1.29-py3-none-win_arm64.whl", hash = "sha256:1ace40f23ab8d8c97f8d61d31d01946ade9c83ea7982671864ec5aef0cd7dd01", size = 51699152, upload-time = "2026-02-27T22:10:15.791Z" }, +] + [[package]] name = "google-api-core" version = "2.30.0" @@ -2323,7 +2360,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/38/3f/9859f655d11901e7b2996c6e3d33e0caa9a1d4572c3bc61ed0faa64b2f4c/greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d", size = 277747, upload-time = "2026-02-20T20:16:21.325Z" }, { url = "https://files.pythonhosted.org/packages/fb/07/cb284a8b5c6498dbd7cba35d31380bb123d7dceaa7907f606c8ff5993cbf/greenlet-3.3.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13", size = 579202, upload-time = "2026-02-20T20:47:28.955Z" }, { url = "https://files.pythonhosted.org/packages/ed/45/67922992b3a152f726163b19f890a85129a992f39607a2a53155de3448b8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e", size = 590620, upload-time = "2026-02-20T20:55:55.581Z" }, - { url = "https://files.pythonhosted.org/packages/03/5f/6e2a7d80c353587751ef3d44bb947f0565ec008a2e0927821c007e96d3a7/greenlet-3.3.2-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7", size = 602132, upload-time = "2026-02-20T21:02:43.261Z" }, { url = "https://files.pythonhosted.org/packages/ad/55/9f1ebb5a825215fadcc0f7d5073f6e79e3007e3282b14b22d6aba7ca6cb8/greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f", size = 591729, upload-time = "2026-02-20T20:20:58.395Z" }, { url = "https://files.pythonhosted.org/packages/24/b4/21f5455773d37f94b866eb3cf5caed88d6cea6dd2c6e1f9c34f463cba3ec/greenlet-3.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef", size = 1551946, upload-time = "2026-02-20T20:49:31.102Z" }, { url = "https://files.pythonhosted.org/packages/00/68/91f061a926abead128fe1a87f0b453ccf07368666bd59ffa46016627a930/greenlet-3.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca", size = 1618494, upload-time = "2026-02-20T20:21:06.541Z" }, @@ -2331,7 +2367,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f3/47/16400cb42d18d7a6bb46f0626852c1718612e35dcb0dffa16bbaffdf5dd2/greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86", size = 278890, upload-time = "2026-02-20T20:19:39.263Z" }, { url = "https://files.pythonhosted.org/packages/a3/90/42762b77a5b6aa96cd8c0e80612663d39211e8ae8a6cd47c7f1249a66262/greenlet-3.3.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f", size = 581120, upload-time = "2026-02-20T20:47:30.161Z" }, { url = "https://files.pythonhosted.org/packages/bf/6f/f3d64f4fa0a9c7b5c5b3c810ff1df614540d5aa7d519261b53fba55d4df9/greenlet-3.3.2-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55", size = 594363, upload-time = "2026-02-20T20:55:56.965Z" }, - { url = "https://files.pythonhosted.org/packages/9c/8b/1430a04657735a3f23116c2e0d5eb10220928846e4537a938a41b350bed6/greenlet-3.3.2-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2", size = 605046, upload-time = "2026-02-20T21:02:45.234Z" }, { url = "https://files.pythonhosted.org/packages/72/83/3e06a52aca8128bdd4dcd67e932b809e76a96ab8c232a8b025b2850264c5/greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358", size = 594156, upload-time = "2026-02-20T20:20:59.955Z" }, { url = "https://files.pythonhosted.org/packages/70/79/0de5e62b873e08fe3cef7dbe84e5c4bc0e8ed0c7ff131bccb8405cd107c8/greenlet-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99", size = 1554649, upload-time = "2026-02-20T20:49:32.293Z" }, { url = "https://files.pythonhosted.org/packages/5a/00/32d30dee8389dc36d42170a9c66217757289e2afb0de59a3565260f38373/greenlet-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be", size = 1619472, upload-time = "2026-02-20T20:21:07.966Z" }, @@ -2340,7 +2375,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ea/ab/1608e5a7578e62113506740b88066bf09888322a311cff602105e619bd87/greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd", size = 280358, upload-time = "2026-02-20T20:17:43.971Z" }, { url = "https://files.pythonhosted.org/packages/a5/23/0eae412a4ade4e6623ff7626e38998cb9b11e9ff1ebacaa021e4e108ec15/greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd", size = 601217, upload-time = "2026-02-20T20:47:31.462Z" }, { url = "https://files.pythonhosted.org/packages/f8/16/5b1678a9c07098ecb9ab2dd159fafaf12e963293e61ee8d10ecb55273e5e/greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac", size = 611792, upload-time = "2026-02-20T20:55:58.423Z" }, - { url = "https://files.pythonhosted.org/packages/5c/c5/cc09412a29e43406eba18d61c70baa936e299bc27e074e2be3806ed29098/greenlet-3.3.2-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb", size = 626250, upload-time = "2026-02-20T21:02:46.596Z" }, { url = "https://files.pythonhosted.org/packages/50/1f/5155f55bd71cabd03765a4aac9ac446be129895271f73872c36ebd4b04b6/greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070", size = 613875, upload-time = "2026-02-20T20:21:01.102Z" }, { url = "https://files.pythonhosted.org/packages/fc/dd/845f249c3fcd69e32df80cdab059b4be8b766ef5830a3d0aa9d6cad55beb/greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79", size = 1571467, upload-time = "2026-02-20T20:49:33.495Z" }, { url = "https://files.pythonhosted.org/packages/2a/50/2649fe21fcc2b56659a452868e695634722a6655ba245d9f77f5656010bf/greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395", size = 1640001, upload-time = "2026-02-20T20:21:09.154Z" }, @@ -2349,7 +2383,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4", size = 279120, upload-time = "2026-02-20T20:19:01.9Z" }, { url = "https://files.pythonhosted.org/packages/49/8d/9771d03e7a8b1ee456511961e1b97a6d77ae1dea4a34a5b98eee706689d3/greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986", size = 603238, upload-time = "2026-02-20T20:47:32.873Z" }, { url = "https://files.pythonhosted.org/packages/59/0e/4223c2bbb63cd5c97f28ffb2a8aee71bdfb30b323c35d409450f51b91e3e/greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92", size = 614219, upload-time = "2026-02-20T20:55:59.817Z" }, - { url = "https://files.pythonhosted.org/packages/94/2b/4d012a69759ac9d77210b8bfb128bc621125f5b20fc398bce3940d036b1c/greenlet-3.3.2-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd", size = 628268, upload-time = "2026-02-20T21:02:48.024Z" }, { url = "https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab", size = 616774, upload-time = "2026-02-20T20:21:02.454Z" }, { url = "https://files.pythonhosted.org/packages/0a/03/996c2d1689d486a6e199cb0f1cf9e4aa940c500e01bdf201299d7d61fa69/greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a", size = 1571277, upload-time = "2026-02-20T20:49:34.795Z" }, { url = "https://files.pythonhosted.org/packages/d9/c4/2570fc07f34a39f2caf0bf9f24b0a1a0a47bc2e8e465b2c2424821389dfc/greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b", size = 1640455, upload-time = "2026-02-20T20:21:10.261Z" }, @@ -2358,7 +2391,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3f/ae/8bffcbd373b57a5992cd077cbe8858fff39110480a9d50697091faea6f39/greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab", size = 279650, upload-time = "2026-02-20T20:18:00.783Z" }, { url = "https://files.pythonhosted.org/packages/d1/c0/45f93f348fa49abf32ac8439938726c480bd96b2a3c6f4d949ec0124b69f/greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082", size = 650295, upload-time = "2026-02-20T20:47:34.036Z" }, { url = "https://files.pythonhosted.org/packages/b3/de/dd7589b3f2b8372069ab3e4763ea5329940fc7ad9dcd3e272a37516d7c9b/greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9", size = 662163, upload-time = "2026-02-20T20:56:01.295Z" }, - { url = "https://files.pythonhosted.org/packages/cd/ac/85804f74f1ccea31ba518dcc8ee6f14c79f73fe36fa1beba38930806df09/greenlet-3.3.2-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9", size = 675371, upload-time = "2026-02-20T21:02:49.664Z" }, { url = "https://files.pythonhosted.org/packages/d2/d8/09bfa816572a4d83bccd6750df1926f79158b1c36c5f73786e26dbe4ee38/greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506", size = 664160, upload-time = "2026-02-20T20:21:04.015Z" }, { url = "https://files.pythonhosted.org/packages/48/cf/56832f0c8255d27f6c35d41b5ec91168d74ec721d85f01a12131eec6b93c/greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce", size = 1619181, upload-time = "2026-02-20T20:49:36.052Z" }, { url = "https://files.pythonhosted.org/packages/0a/23/b90b60a4aabb4cec0796e55f25ffbfb579a907c3898cd2905c8918acaa16/greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5", size = 1687713, upload-time = "2026-02-20T20:21:11.684Z" }, @@ -2367,7 +2399,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/98/6d/8f2ef704e614bcf58ed43cfb8d87afa1c285e98194ab2cfad351bf04f81e/greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54", size = 286617, upload-time = "2026-02-20T20:19:29.856Z" }, { url = "https://files.pythonhosted.org/packages/5e/0d/93894161d307c6ea237a43988f27eba0947b360b99ac5239ad3fe09f0b47/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4", size = 655189, upload-time = "2026-02-20T20:47:35.742Z" }, { url = "https://files.pythonhosted.org/packages/f5/2c/d2d506ebd8abcb57386ec4f7ba20f4030cbe56eae541bc6fd6ef399c0b41/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff", size = 658225, upload-time = "2026-02-20T20:56:02.527Z" }, - { url = "https://files.pythonhosted.org/packages/d1/67/8197b7e7e602150938049d8e7f30de1660cfb87e4c8ee349b42b67bdb2e1/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf", size = 666581, upload-time = "2026-02-20T21:02:51.526Z" }, { url = "https://files.pythonhosted.org/packages/8e/30/3a09155fbf728673a1dea713572d2d31159f824a37c22da82127056c44e4/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4", size = 657907, upload-time = "2026-02-20T20:21:05.259Z" }, { url = "https://files.pythonhosted.org/packages/f3/fd/d05a4b7acd0154ed758797f0a43b4c0962a843bedfe980115e842c5b2d08/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727", size = 1618857, upload-time = "2026-02-20T20:49:37.309Z" }, { url = "https://files.pythonhosted.org/packages/6f/e1/50ee92a5db521de8f35075b5eff060dd43d39ebd46c2181a2042f7070385/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e", size = 1680010, upload-time = "2026-02-20T20:21:13.427Z" }, @@ -2446,7 +2477,7 @@ wheels = [ [[package]] name = "grpcio" -version = "1.78.1" +version = "1.78.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.14' and sys_platform == 'darwin'", @@ -2456,58 +2487,58 @@ resolution-markers = [ dependencies = [ { name = "typing-extensions", marker = "(python_full_version >= '3.14' and sys_platform == 'darwin') or (python_full_version >= '3.14' and sys_platform == 'linux') or (python_full_version >= '3.14' and sys_platform == 'win32')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/1f/de/de568532d9907552700f80dcec38219d8d298ad9e71f5e0a095abaf2761e/grpcio-1.78.1.tar.gz", hash = "sha256:27c625532d33ace45d57e775edf1982e183ff8641c72e4e91ef7ba667a149d72", size = 12835760, upload-time = "2026-02-20T01:16:10.869Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/44/30/0534b643dafd54824769d6260b89c71d518e4ef8b5ad16b84d1ae9272978/grpcio-1.78.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:4393bef64cf26dc07cd6f18eaa5170ae4eebaafd4418e7e3a59ca9526a6fa30b", size = 5947661, upload-time = "2026-02-20T01:12:34.922Z" }, - { url = "https://files.pythonhosted.org/packages/4a/f8/f678566655ab822da0f713789555e7eddca7ef93da99f480c63de3aa94b4/grpcio-1.78.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:917047c19cd120b40aab9a4b8a22e9ce3562f4a1343c0d62b3cd2d5199da3d67", size = 11819948, upload-time = "2026-02-20T01:12:39.709Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0b/a4b4210d946055f4e5a8430f2802202ae8f831b4b00d36d55055c5cf4b6a/grpcio-1.78.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff7de398bb3528d44d17e6913a7cfe639e3b15c65595a71155322df16978c5e1", size = 6519850, upload-time = "2026-02-20T01:12:42.715Z" }, - { url = "https://files.pythonhosted.org/packages/ea/d9/a1e657a73000a71fa75ec7140ff3a8dc32eb3427560620e477c6a2735527/grpcio-1.78.1-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:15f6e636d1152667ddb4022b37534c161c8477274edb26a0b65b215dd0a81e97", size = 7198654, upload-time = "2026-02-20T01:12:46.164Z" }, - { url = "https://files.pythonhosted.org/packages/aa/28/a61c5bdf53c1638e657bb5eebb93c789837820e1fdb965145f05eccc2994/grpcio-1.78.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:27b5cb669603efb7883a882275db88b6b5d6b6c9f0267d5846ba8699b7ace338", size = 6727238, upload-time = "2026-02-20T01:12:48.472Z" }, - { url = "https://files.pythonhosted.org/packages/9d/3e/aa143d0687801986a29d85788c96089449f36651cd4e2a493737ae0c5be9/grpcio-1.78.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:86edb3966778fa05bfdb333688fde5dc9079f9e2a9aa6a5c42e9564b7656ba04", size = 7300960, upload-time = "2026-02-20T01:12:51.139Z" }, - { url = "https://files.pythonhosted.org/packages/30/d3/53e0f26b46417f28d14b5951fc6a1eff79c08c8a339e967c0a19ec7cf9e9/grpcio-1.78.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:849cc62eb989bc3be5629d4f3acef79be0d0ff15622201ed251a86d17fef6494", size = 8285274, upload-time = "2026-02-20T01:12:53.315Z" }, - { url = "https://files.pythonhosted.org/packages/29/d0/e0e9fd477ce86c07ed1ed1d5c34790f050b6d58bfde77b02b36e23f8b235/grpcio-1.78.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9a00992d6fafe19d648b9ccb4952200c50d8e36d0cce8cf026c56ed3fdc28465", size = 7726620, upload-time = "2026-02-20T01:12:56.498Z" }, - { url = "https://files.pythonhosted.org/packages/5e/b5/e138a9f7810d196081b2e047c378ca12358c5906d79c42ddec41bb43d528/grpcio-1.78.1-cp310-cp310-win32.whl", hash = "sha256:f8759a1347f3b4f03d9a9d4ce8f9f31ad5e5d0144ba06ccfb1ffaeb0ba4c1e20", size = 4076778, upload-time = "2026-02-20T01:12:59.098Z" }, - { url = "https://files.pythonhosted.org/packages/4e/95/9b02316b85731df0943a635ca6d02f155f673c4f17e60be0c4892a6eb051/grpcio-1.78.1-cp310-cp310-win_amd64.whl", hash = "sha256:e840405a3f1249509892be2399f668c59b9d492068a2cf326d661a8c79e5e747", size = 4798925, upload-time = "2026-02-20T01:13:03.186Z" }, - { url = "https://files.pythonhosted.org/packages/bf/1e/ad774af3b2c84f49c6d8c4a7bea4c40f02268ea8380630c28777edda463b/grpcio-1.78.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:3a8aa79bc6e004394c0abefd4b034c14affda7b66480085d87f5fbadf43b593b", size = 5951132, upload-time = "2026-02-20T01:13:05.942Z" }, - { url = "https://files.pythonhosted.org/packages/48/9d/ad3c284bedd88c545e20675d98ae904114d8517a71b0efc0901e9166628f/grpcio-1.78.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:8e1fcb419da5811deb47b7749b8049f7c62b993ba17822e3c7231e3e0ba65b79", size = 11831052, upload-time = "2026-02-20T01:13:09.604Z" }, - { url = "https://files.pythonhosted.org/packages/6d/08/20d12865e47242d03c3ade9bb2127f5b4aded964f373284cfb357d47c5ac/grpcio-1.78.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b071dccac245c32cd6b1dd96b722283b855881ca0bf1c685cf843185f5d5d51e", size = 6524749, upload-time = "2026-02-20T01:13:21.692Z" }, - { url = "https://files.pythonhosted.org/packages/c6/53/a8b72f52b253ec0cfdf88a13e9236a9d717c332b8aa5f0ba9e4699e94b55/grpcio-1.78.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:d6fb962947e4fe321eeef3be1ba5ba49d32dea9233c825fcbade8e858c14aaf4", size = 7198995, upload-time = "2026-02-20T01:13:24.275Z" }, - { url = "https://files.pythonhosted.org/packages/13/3c/ac769c8ded1bcb26bb119fb472d3374b481b3cf059a0875db9fc77139c17/grpcio-1.78.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a6afd191551fd72e632367dfb083e33cd185bf9ead565f2476bba8ab864ae496", size = 6730770, upload-time = "2026-02-20T01:13:26.522Z" }, - { url = "https://files.pythonhosted.org/packages/dc/c3/2275ef4cc5b942314321f77d66179be4097ff484e82ca34bf7baa5b1ddbc/grpcio-1.78.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b2acd83186305c0802dbc4d81ed0ec2f3e8658d7fde97cfba2f78d7372f05b89", size = 7305036, upload-time = "2026-02-20T01:13:30.923Z" }, - { url = "https://files.pythonhosted.org/packages/91/cb/3c2aa99e12cbbfc72c2ed8aa328e6041709d607d668860380e6cd00ba17d/grpcio-1.78.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5380268ab8513445740f1f77bd966d13043d07e2793487e61fd5b5d0935071eb", size = 8288641, upload-time = "2026-02-20T01:13:39.42Z" }, - { url = "https://files.pythonhosted.org/packages/0d/b2/21b89f492260ac645775d9973752ca873acfd0609d6998e9d3065a21ea2f/grpcio-1.78.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:389b77484959bdaad6a2b7dda44d7d1228381dd669a03f5660392aa0e9385b22", size = 7730967, upload-time = "2026-02-20T01:13:41.697Z" }, - { url = "https://files.pythonhosted.org/packages/24/03/6b89eddf87fdffb8fa9d37375d44d3a798f4b8116ac363a5f7ca84caa327/grpcio-1.78.1-cp311-cp311-win32.whl", hash = "sha256:9dee66d142f4a8cca36b5b98a38f006419138c3c89e72071747f8fca415a6d8f", size = 4076680, upload-time = "2026-02-20T01:13:43.781Z" }, - { url = "https://files.pythonhosted.org/packages/a7/a8/204460b1bc1dff9862e98f56a2d14be3c4171f929f8eaf8c4517174b4270/grpcio-1.78.1-cp311-cp311-win_amd64.whl", hash = "sha256:43b930cf4f9c4a2262bb3e5d5bc40df426a72538b4f98e46f158b7eb112d2d70", size = 4801074, upload-time = "2026-02-20T01:13:46.315Z" }, - { url = "https://files.pythonhosted.org/packages/ab/ed/d2eb9d27fded1a76b2a80eb9aa8b12101da7e41ce2bac0ad3651e88a14ae/grpcio-1.78.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:41e4605c923e0e9a84a2718e4948a53a530172bfaf1a6d1ded16ef9c5849fca2", size = 5913389, upload-time = "2026-02-20T01:13:49.005Z" }, - { url = "https://files.pythonhosted.org/packages/69/1b/40034e9ab010eeb3fa41ec61d8398c6dbf7062f3872c866b8f72700e2522/grpcio-1.78.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:39da1680d260c0c619c3b5fa2dc47480ca24d5704c7a548098bca7de7f5dd17f", size = 11811839, upload-time = "2026-02-20T01:13:51.839Z" }, - { url = "https://files.pythonhosted.org/packages/b4/69/fe16ef2979ea62b8aceb3a3f1e7a8bbb8b717ae2a44b5899d5d426073273/grpcio-1.78.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b5d5881d72a09b8336a8f874784a8eeffacde44a7bc1a148bce5a0243a265ef0", size = 6475805, upload-time = "2026-02-20T01:13:55.423Z" }, - { url = "https://files.pythonhosted.org/packages/5b/1e/069e0a9062167db18446917d7c00ae2e91029f96078a072bedc30aaaa8c3/grpcio-1.78.1-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:888ceb7821acd925b1c90f0cdceaed1386e69cfe25e496e0771f6c35a156132f", size = 7169955, upload-time = "2026-02-20T01:13:59.553Z" }, - { url = "https://files.pythonhosted.org/packages/38/fc/44a57e2bb4a755e309ee4e9ed2b85c9af93450b6d3118de7e69410ee05fa/grpcio-1.78.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8942bdfc143b467c264b048862090c4ba9a0223c52ae28c9ae97754361372e42", size = 6690767, upload-time = "2026-02-20T01:14:02.31Z" }, - { url = "https://files.pythonhosted.org/packages/b8/87/21e16345d4c75046d453916166bc72a3309a382c8e97381ec4b8c1a54729/grpcio-1.78.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:716a544969660ed609164aff27b2effd3ff84e54ac81aa4ce77b1607ca917d22", size = 7266846, upload-time = "2026-02-20T01:14:12.974Z" }, - { url = "https://files.pythonhosted.org/packages/11/df/d6261983f9ca9ef4d69893765007a9a3211b91d9faf85a2591063df381c7/grpcio-1.78.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4d50329b081c223d444751076bb5b389d4f06c2b32d51b31a1e98172e6cecfb9", size = 8253522, upload-time = "2026-02-20T01:14:17.407Z" }, - { url = "https://files.pythonhosted.org/packages/de/7c/4f96a0ff113c5d853a27084d7590cd53fdb05169b596ea9f5f27f17e021e/grpcio-1.78.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7e836778c13ff70edada16567e8da0c431e8818eaae85b80d11c1ba5782eccbb", size = 7698070, upload-time = "2026-02-20T01:14:20.032Z" }, - { url = "https://files.pythonhosted.org/packages/17/3c/7b55c0b5af88fbeb3d0c13e25492d3ace41ac9dbd0f5f8f6c0fb613b6706/grpcio-1.78.1-cp312-cp312-win32.whl", hash = "sha256:07eb016ea7444a22bef465cce045512756956433f54450aeaa0b443b8563b9ca", size = 4066474, upload-time = "2026-02-20T01:14:22.602Z" }, - { url = "https://files.pythonhosted.org/packages/5d/17/388c12d298901b0acf10b612b650692bfed60e541672b1d8965acbf2d722/grpcio-1.78.1-cp312-cp312-win_amd64.whl", hash = "sha256:02b82dcd2fa580f5e82b4cf62ecde1b3c7cc9ba27b946421200706a6e5acaf85", size = 4797537, upload-time = "2026-02-20T01:14:25.444Z" }, - { url = "https://files.pythonhosted.org/packages/df/72/754754639cfd16ad04619e1435a518124b2d858e5752225376f9285d4c51/grpcio-1.78.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:2b7ad2981550ce999e25ce3f10c8863f718a352a2fd655068d29ea3fd37b4907", size = 5919437, upload-time = "2026-02-20T01:14:29.403Z" }, - { url = "https://files.pythonhosted.org/packages/5c/84/6267d1266f8bc335d3a8b7ccf981be7de41e3ed8bd3a49e57e588212b437/grpcio-1.78.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:409bfe22220889b9906739910a0ee4c197a967c21b8dd14b4b06dd477f8819ce", size = 11803701, upload-time = "2026-02-20T01:14:32.624Z" }, - { url = "https://files.pythonhosted.org/packages/f3/56/c9098e8b920a54261cd605bbb040de0cde1ca4406102db0aa2c0b11d1fb4/grpcio-1.78.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:34b6cb16f4b67eeb5206250dc5b4d5e8e3db939535e58efc330e4c61341554bd", size = 6479416, upload-time = "2026-02-20T01:14:35.926Z" }, - { url = "https://files.pythonhosted.org/packages/86/cf/5d52024371ee62658b7ed72480200524087528844ec1b65265bbcd31c974/grpcio-1.78.1-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:39d21fd30d38a5afb93f0e2e71e2ec2bd894605fb75d41d5a40060c2f98f8d11", size = 7174087, upload-time = "2026-02-20T01:14:39.98Z" }, - { url = "https://files.pythonhosted.org/packages/31/e6/5e59551afad4279e27335a6d60813b8aa3ae7b14fb62cea1d329a459c118/grpcio-1.78.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:09fbd4bcaadb6d8604ed1504b0bdf7ac18e48467e83a9d930a70a7fefa27e862", size = 6692881, upload-time = "2026-02-20T01:14:42.466Z" }, - { url = "https://files.pythonhosted.org/packages/db/8f/940062de2d14013c02f51b079eb717964d67d46f5d44f22038975c9d9576/grpcio-1.78.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:db681513a1bdd879c0b24a5a6a70398da5eaaba0e077a306410dc6008426847a", size = 7269092, upload-time = "2026-02-20T01:14:45.826Z" }, - { url = "https://files.pythonhosted.org/packages/09/87/9db657a4b5f3b15560ec591db950bc75a1a2f9e07832578d7e2b23d1a7bd/grpcio-1.78.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f81816faa426da461e9a597a178832a351d6f1078102590a4b32c77d251b71eb", size = 8252037, upload-time = "2026-02-20T01:14:48.57Z" }, - { url = "https://files.pythonhosted.org/packages/e2/37/b980e0265479ec65e26b6e300a39ceac33ecb3f762c2861d4bac990317cf/grpcio-1.78.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffbb760df1cd49e0989f9826b2fd48930700db6846ac171eaff404f3cfbe5c28", size = 7695243, upload-time = "2026-02-20T01:14:51.376Z" }, - { url = "https://files.pythonhosted.org/packages/98/46/5fc42c100ab702fa1ea41a75c890c563c3f96432b4a287d5a6369654f323/grpcio-1.78.1-cp313-cp313-win32.whl", hash = "sha256:1a56bf3ee99af5cf32d469de91bf5de79bdac2e18082b495fc1063ea33f4f2d0", size = 4065329, upload-time = "2026-02-20T01:14:53.952Z" }, - { url = "https://files.pythonhosted.org/packages/b0/da/806d60bb6611dfc16cf463d982bd92bd8b6bd5f87dfac66b0a44dfe20995/grpcio-1.78.1-cp313-cp313-win_amd64.whl", hash = "sha256:8991c2add0d8505178ff6c3ae54bd9386279e712be82fa3733c54067aae9eda1", size = 4797637, upload-time = "2026-02-20T01:14:57.276Z" }, - { url = "https://files.pythonhosted.org/packages/96/3a/2d2ec4d2ce2eb9d6a2b862630a0d9d4ff4239ecf1474ecff21442a78612a/grpcio-1.78.1-cp314-cp314-linux_armv7l.whl", hash = "sha256:d101fe49b1e0fb4a7aa36ed0c3821a0f67a5956ef572745452d2cd790d723a3f", size = 5920256, upload-time = "2026-02-20T01:15:00.23Z" }, - { url = "https://files.pythonhosted.org/packages/9c/92/dccb7d087a1220ed358753945230c1ddeeed13684b954cb09db6758f1271/grpcio-1.78.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:5ce1855e8cfc217cdf6bcfe0cf046d7cf81ddcc3e6894d6cfd075f87a2d8f460", size = 11813749, upload-time = "2026-02-20T01:15:03.312Z" }, - { url = "https://files.pythonhosted.org/packages/ef/47/c20e87f87986da9998f30f14776ce27e61f02482a3a030ffe265089342c6/grpcio-1.78.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd26048d066b51f39fe9206e2bcc2cea869a5e5b2d13c8d523f4179193047ebd", size = 6488739, upload-time = "2026-02-20T01:15:14.349Z" }, - { url = "https://files.pythonhosted.org/packages/a6/c2/088bd96e255133d7d87c3eed0d598350d16cde1041bdbe2bb065967aaf91/grpcio-1.78.1-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4b8d7fda614cf2af0f73bbb042f3b7fee2ecd4aea69ec98dbd903590a1083529", size = 7173096, upload-time = "2026-02-20T01:15:17.687Z" }, - { url = "https://files.pythonhosted.org/packages/60/ce/168db121073a03355ce3552b3b1f790b5ded62deffd7d98c5f642b9d3d81/grpcio-1.78.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:656a5bd142caeb8b1efe1fe0b4434ecc7781f44c97cfc7927f6608627cf178c0", size = 6693861, upload-time = "2026-02-20T01:15:20.911Z" }, - { url = "https://files.pythonhosted.org/packages/ae/d0/90b30ec2d9425215dd56922d85a90babbe6ee7e8256ba77d866b9c0d3aba/grpcio-1.78.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:99550e344482e3c21950c034f74668fccf8a546d50c1ecb4f717543bbdc071ba", size = 7278083, upload-time = "2026-02-20T01:15:23.698Z" }, - { url = "https://files.pythonhosted.org/packages/c1/fb/73f9ba0b082bcd385d46205095fd9c917754685885b28fce3741e9f54529/grpcio-1.78.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8f27683ca68359bd3f0eb4925824d71e538f84338b3ae337ead2ae43977d7541", size = 8252546, upload-time = "2026-02-20T01:15:26.517Z" }, - { url = "https://files.pythonhosted.org/packages/85/c5/6a89ea3cb5db6c3d9ed029b0396c49f64328c0cf5d2630ffeed25711920a/grpcio-1.78.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a40515b69ac50792f9b8ead260f194ba2bb3285375b6c40c7ff938f14c3df17d", size = 7696289, upload-time = "2026-02-20T01:15:29.718Z" }, - { url = "https://files.pythonhosted.org/packages/3d/05/63a7495048499ef437b4933d32e59b7f737bd5368ad6fb2479e2bd83bf2c/grpcio-1.78.1-cp314-cp314-win32.whl", hash = "sha256:2c473b54ef1618f4fb85e82ff4994de18143b74efc088b91b5a935a3a45042ba", size = 4142186, upload-time = "2026-02-20T01:15:32.786Z" }, - { url = "https://files.pythonhosted.org/packages/1c/ce/adfe7e5f701d503be7778291757452e3fab6b19acf51917c79f5d1cf7f8a/grpcio-1.78.1-cp314-cp314-win_amd64.whl", hash = "sha256:e2a6b33d1050dce2c6f563c5caf7f7cbeebf7fba8cde37ffe3803d50526900d1", size = 4932000, upload-time = "2026-02-20T01:15:36.127Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/06/8a/3d098f35c143a89520e568e6539cc098fcd294495910e359889ce8741c84/grpcio-1.78.0.tar.gz", hash = "sha256:7382b95189546f375c174f53a5fa873cef91c4b8005faa05cc5b3beea9c4f1c5", size = 12852416, upload-time = "2026-02-06T09:57:18.093Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/a8/690a085b4d1fe066130de97a87de32c45062cf2ecd218df9675add895550/grpcio-1.78.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:7cc47943d524ee0096f973e1081cb8f4f17a4615f2116882a5f1416e4cfe92b5", size = 5946986, upload-time = "2026-02-06T09:54:34.043Z" }, + { url = "https://files.pythonhosted.org/packages/c7/1b/e5213c5c0ced9d2d92778d30529ad5bb2dcfb6c48c4e2d01b1f302d33d64/grpcio-1.78.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:c3f293fdc675ccba4db5a561048cca627b5e7bd1c8a6973ffedabe7d116e22e2", size = 11816533, upload-time = "2026-02-06T09:54:37.04Z" }, + { url = "https://files.pythonhosted.org/packages/18/37/1ba32dccf0a324cc5ace744c44331e300b000a924bf14840f948c559ede7/grpcio-1.78.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:10a9a644b5dd5aec3b82b5b0b90d41c0fa94c85ef42cb42cf78a23291ddb5e7d", size = 6519964, upload-time = "2026-02-06T09:54:40.268Z" }, + { url = "https://files.pythonhosted.org/packages/ed/f5/c0e178721b818072f2e8b6fde13faaba942406c634009caf065121ce246b/grpcio-1.78.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:4c5533d03a6cbd7f56acfc9cfb44ea64f63d29091e40e44010d34178d392d7eb", size = 7198058, upload-time = "2026-02-06T09:54:42.389Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b2/40d43c91ae9cd667edc960135f9f08e58faa1576dc95af29f66ec912985f/grpcio-1.78.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ff870aebe9a93a85283837801d35cd5f8814fe2ad01e606861a7fb47c762a2b7", size = 6727212, upload-time = "2026-02-06T09:54:44.91Z" }, + { url = "https://files.pythonhosted.org/packages/ed/88/9da42eed498f0efcfcd9156e48ae63c0cde3bea398a16c99fb5198c885b6/grpcio-1.78.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:391e93548644e6b2726f1bb84ed60048d4bcc424ce5e4af0843d28ca0b754fec", size = 7300845, upload-time = "2026-02-06T09:54:47.562Z" }, + { url = "https://files.pythonhosted.org/packages/23/3f/1c66b7b1b19a8828890e37868411a6e6925df5a9030bfa87ab318f34095d/grpcio-1.78.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:df2c8f3141f7cbd112a6ebbd760290b5849cda01884554f7c67acc14e7b1758a", size = 8284605, upload-time = "2026-02-06T09:54:50.475Z" }, + { url = "https://files.pythonhosted.org/packages/94/c4/ca1bd87394f7b033e88525384b4d1e269e8424ab441ea2fba1a0c5b50986/grpcio-1.78.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd8cb8026e5f5b50498a3c4f196f57f9db344dad829ffae16b82e4fdbaea2813", size = 7726672, upload-time = "2026-02-06T09:54:53.11Z" }, + { url = "https://files.pythonhosted.org/packages/41/09/f16e487d4cc65ccaf670f6ebdd1a17566b965c74fc3d93999d3b2821e052/grpcio-1.78.0-cp310-cp310-win32.whl", hash = "sha256:f8dff3d9777e5d2703a962ee5c286c239bf0ba173877cc68dc02c17d042e29de", size = 4076715, upload-time = "2026-02-06T09:54:55.549Z" }, + { url = "https://files.pythonhosted.org/packages/2a/32/4ce60d94e242725fd3bcc5673c04502c82a8e87b21ea411a63992dc39f8f/grpcio-1.78.0-cp310-cp310-win_amd64.whl", hash = "sha256:94f95cf5d532d0e717eed4fc1810e8e6eded04621342ec54c89a7c2f14b581bf", size = 4799157, upload-time = "2026-02-06T09:54:59.838Z" }, + { url = "https://files.pythonhosted.org/packages/86/c7/d0b780a29b0837bf4ca9580904dfb275c1fc321ded7897d620af7047ec57/grpcio-1.78.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:2777b783f6c13b92bd7b716667452c329eefd646bfb3f2e9dabea2e05dbd34f6", size = 5951525, upload-time = "2026-02-06T09:55:01.989Z" }, + { url = "https://files.pythonhosted.org/packages/c5/b1/96920bf2ee61df85a9503cb6f733fe711c0ff321a5a697d791b075673281/grpcio-1.78.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:9dca934f24c732750389ce49d638069c3892ad065df86cb465b3fa3012b70c9e", size = 11830418, upload-time = "2026-02-06T09:55:04.462Z" }, + { url = "https://files.pythonhosted.org/packages/83/0c/7c1528f098aeb75a97de2bae18c530f56959fb7ad6c882db45d9884d6edc/grpcio-1.78.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:459ab414b35f4496138d0ecd735fed26f1318af5e52cb1efbc82a09f0d5aa911", size = 6524477, upload-time = "2026-02-06T09:55:07.111Z" }, + { url = "https://files.pythonhosted.org/packages/8d/52/e7c1f3688f949058e19a011c4e0dec973da3d0ae5e033909677f967ae1f4/grpcio-1.78.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:082653eecbdf290e6e3e2c276ab2c54b9e7c299e07f4221872380312d8cf395e", size = 7198266, upload-time = "2026-02-06T09:55:10.016Z" }, + { url = "https://files.pythonhosted.org/packages/e5/61/8ac32517c1e856677282c34f2e7812d6c328fa02b8f4067ab80e77fdc9c9/grpcio-1.78.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85f93781028ec63f383f6bc90db785a016319c561cc11151fbb7b34e0d012303", size = 6730552, upload-time = "2026-02-06T09:55:12.207Z" }, + { url = "https://files.pythonhosted.org/packages/bd/98/b8ee0158199250220734f620b12e4a345955ac7329cfd908d0bf0fda77f0/grpcio-1.78.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f12857d24d98441af6a1d5c87442d624411db486f7ba12550b07788f74b67b04", size = 7304296, upload-time = "2026-02-06T09:55:15.044Z" }, + { url = "https://files.pythonhosted.org/packages/bd/0f/7b72762e0d8840b58032a56fdbd02b78fc645b9fa993d71abf04edbc54f4/grpcio-1.78.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5397fff416b79e4b284959642a4e95ac4b0f1ece82c9993658e0e477d40551ec", size = 8288298, upload-time = "2026-02-06T09:55:17.276Z" }, + { url = "https://files.pythonhosted.org/packages/24/ae/ae4ce56bc5bb5caa3a486d60f5f6083ac3469228faa734362487176c15c5/grpcio-1.78.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbe6e89c7ffb48518384068321621b2a69cab509f58e40e4399fdd378fa6d074", size = 7730953, upload-time = "2026-02-06T09:55:19.545Z" }, + { url = "https://files.pythonhosted.org/packages/b5/6e/8052e3a28eb6a820c372b2eb4b5e32d195c661e137d3eca94d534a4cfd8a/grpcio-1.78.0-cp311-cp311-win32.whl", hash = "sha256:6092beabe1966a3229f599d7088b38dfc8ffa1608b5b5cdda31e591e6500f856", size = 4076503, upload-time = "2026-02-06T09:55:21.521Z" }, + { url = "https://files.pythonhosted.org/packages/08/62/f22c98c5265dfad327251fa2f840b591b1df5f5e15d88b19c18c86965b27/grpcio-1.78.0-cp311-cp311-win_amd64.whl", hash = "sha256:1afa62af6e23f88629f2b29ec9e52ec7c65a7176c1e0a83292b93c76ca882558", size = 4799767, upload-time = "2026-02-06T09:55:24.107Z" }, + { url = "https://files.pythonhosted.org/packages/4e/f4/7384ed0178203d6074446b3c4f46c90a22ddf7ae0b3aee521627f54cfc2a/grpcio-1.78.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:f9ab915a267fc47c7e88c387a3a28325b58c898e23d4995f765728f4e3dedb97", size = 5913985, upload-time = "2026-02-06T09:55:26.832Z" }, + { url = "https://files.pythonhosted.org/packages/81/ed/be1caa25f06594463f685b3790b320f18aea49b33166f4141bfdc2bfb236/grpcio-1.78.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3f8904a8165ab21e07e58bf3e30a73f4dffc7a1e0dbc32d51c61b5360d26f43e", size = 11811853, upload-time = "2026-02-06T09:55:29.224Z" }, + { url = "https://files.pythonhosted.org/packages/24/a7/f06d151afc4e64b7e3cc3e872d331d011c279aaab02831e40a81c691fb65/grpcio-1.78.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:859b13906ce098c0b493af92142ad051bf64c7870fa58a123911c88606714996", size = 6475766, upload-time = "2026-02-06T09:55:31.825Z" }, + { url = "https://files.pythonhosted.org/packages/8a/a8/4482922da832ec0082d0f2cc3a10976d84a7424707f25780b82814aafc0a/grpcio-1.78.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b2342d87af32790f934a79c3112641e7b27d63c261b8b4395350dad43eff1dc7", size = 7170027, upload-time = "2026-02-06T09:55:34.7Z" }, + { url = "https://files.pythonhosted.org/packages/54/bf/f4a3b9693e35d25b24b0b39fa46d7d8a3c439e0a3036c3451764678fec20/grpcio-1.78.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12a771591ae40bc65ba67048fa52ef4f0e6db8279e595fd349f9dfddeef571f9", size = 6690766, upload-time = "2026-02-06T09:55:36.902Z" }, + { url = "https://files.pythonhosted.org/packages/c7/b9/521875265cc99fe5ad4c5a17010018085cae2810a928bf15ebe7d8bcd9cc/grpcio-1.78.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:185dea0d5260cbb2d224c507bf2a5444d5abbb1fa3594c1ed7e4c709d5eb8383", size = 7266161, upload-time = "2026-02-06T09:55:39.824Z" }, + { url = "https://files.pythonhosted.org/packages/05/86/296a82844fd40a4ad4a95f100b55044b4f817dece732bf686aea1a284147/grpcio-1.78.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:51b13f9aed9d59ee389ad666b8c2214cc87b5de258fa712f9ab05f922e3896c6", size = 8253303, upload-time = "2026-02-06T09:55:42.353Z" }, + { url = "https://files.pythonhosted.org/packages/f3/e4/ea3c0caf5468537f27ad5aab92b681ed7cc0ef5f8c9196d3fd42c8c2286b/grpcio-1.78.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fd5f135b1bd58ab088930b3c613455796dfa0393626a6972663ccdda5b4ac6ce", size = 7698222, upload-time = "2026-02-06T09:55:44.629Z" }, + { url = "https://files.pythonhosted.org/packages/d7/47/7f05f81e4bb6b831e93271fb12fd52ba7b319b5402cbc101d588f435df00/grpcio-1.78.0-cp312-cp312-win32.whl", hash = "sha256:94309f498bcc07e5a7d16089ab984d42ad96af1d94b5a4eb966a266d9fcabf68", size = 4066123, upload-time = "2026-02-06T09:55:47.644Z" }, + { url = "https://files.pythonhosted.org/packages/ad/e7/d6914822c88aa2974dbbd10903d801a28a19ce9cd8bad7e694cbbcf61528/grpcio-1.78.0-cp312-cp312-win_amd64.whl", hash = "sha256:9566fe4ababbb2610c39190791e5b829869351d14369603702e890ef3ad2d06e", size = 4797657, upload-time = "2026-02-06T09:55:49.86Z" }, + { url = "https://files.pythonhosted.org/packages/05/a9/8f75894993895f361ed8636cd9237f4ab39ef87fd30db17467235ed1c045/grpcio-1.78.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:ce3a90455492bf8bfa38e56fbbe1dbd4f872a3d8eeaf7337dc3b1c8aa28c271b", size = 5920143, upload-time = "2026-02-06T09:55:52.035Z" }, + { url = "https://files.pythonhosted.org/packages/55/06/0b78408e938ac424100100fd081189451b472236e8a3a1f6500390dc4954/grpcio-1.78.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:2bf5e2e163b356978b23652c4818ce4759d40f4712ee9ec5a83c4be6f8c23a3a", size = 11803926, upload-time = "2026-02-06T09:55:55.494Z" }, + { url = "https://files.pythonhosted.org/packages/88/93/b59fe7832ff6ae3c78b813ea43dac60e295fa03606d14d89d2e0ec29f4f3/grpcio-1.78.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8f2ac84905d12918e4e55a16da17939eb63e433dc11b677267c35568aa63fc84", size = 6478628, upload-time = "2026-02-06T09:55:58.533Z" }, + { url = "https://files.pythonhosted.org/packages/ed/df/e67e3734527f9926b7d9c0dde6cd998d1d26850c3ed8eeec81297967ac67/grpcio-1.78.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b58f37edab4a3881bc6c9bca52670610e0c9ca14e2ea3cf9debf185b870457fb", size = 7173574, upload-time = "2026-02-06T09:56:01.786Z" }, + { url = "https://files.pythonhosted.org/packages/a6/62/cc03fffb07bfba982a9ec097b164e8835546980aec25ecfa5f9c1a47e022/grpcio-1.78.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:735e38e176a88ce41840c21bb49098ab66177c64c82426e24e0082500cc68af5", size = 6692639, upload-time = "2026-02-06T09:56:04.529Z" }, + { url = "https://files.pythonhosted.org/packages/bf/9a/289c32e301b85bdb67d7ec68b752155e674ee3ba2173a1858f118e399ef3/grpcio-1.78.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2045397e63a7a0ee7957c25f7dbb36ddc110e0cfb418403d110c0a7a68a844e9", size = 7268838, upload-time = "2026-02-06T09:56:08.397Z" }, + { url = "https://files.pythonhosted.org/packages/0e/79/1be93f32add280461fa4773880196572563e9c8510861ac2da0ea0f892b6/grpcio-1.78.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a9f136fbafe7ccf4ac7e8e0c28b31066e810be52d6e344ef954a3a70234e1702", size = 8251878, upload-time = "2026-02-06T09:56:10.914Z" }, + { url = "https://files.pythonhosted.org/packages/65/65/793f8e95296ab92e4164593674ae6291b204bb5f67f9d4a711489cd30ffa/grpcio-1.78.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:748b6138585379c737adc08aeffd21222abbda1a86a0dca2a39682feb9196c20", size = 7695412, upload-time = "2026-02-06T09:56:13.593Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9f/1e233fe697ecc82845942c2822ed06bb522e70d6771c28d5528e4c50f6a4/grpcio-1.78.0-cp313-cp313-win32.whl", hash = "sha256:271c73e6e5676afe4fc52907686670c7cea22ab2310b76a59b678403ed40d670", size = 4064899, upload-time = "2026-02-06T09:56:15.601Z" }, + { url = "https://files.pythonhosted.org/packages/4d/27/d86b89e36de8a951501fb06a0f38df19853210f341d0b28f83f4aa0ffa08/grpcio-1.78.0-cp313-cp313-win_amd64.whl", hash = "sha256:f2d4e43ee362adfc05994ed479334d5a451ab7bc3f3fee1b796b8ca66895acb4", size = 4797393, upload-time = "2026-02-06T09:56:17.882Z" }, + { url = "https://files.pythonhosted.org/packages/29/f2/b56e43e3c968bfe822fa6ce5bca10d5c723aa40875b48791ce1029bb78c7/grpcio-1.78.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:e87cbc002b6f440482b3519e36e1313eb5443e9e9e73d6a52d43bd2004fcfd8e", size = 5920591, upload-time = "2026-02-06T09:56:20.758Z" }, + { url = "https://files.pythonhosted.org/packages/5d/81/1f3b65bd30c334167bfa8b0d23300a44e2725ce39bba5b76a2460d85f745/grpcio-1.78.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:c41bc64626db62e72afec66b0c8a0da76491510015417c127bfc53b2fe6d7f7f", size = 11813685, upload-time = "2026-02-06T09:56:24.315Z" }, + { url = "https://files.pythonhosted.org/packages/0e/1c/bbe2f8216a5bd3036119c544d63c2e592bdf4a8ec6e4a1867592f4586b26/grpcio-1.78.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8dfffba826efcf366b1e3ccc37e67afe676f290e13a3b48d31a46739f80a8724", size = 6487803, upload-time = "2026-02-06T09:56:27.367Z" }, + { url = "https://files.pythonhosted.org/packages/16/5c/a6b2419723ea7ddce6308259a55e8e7593d88464ce8db9f4aa857aba96fa/grpcio-1.78.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:74be1268d1439eaaf552c698cdb11cd594f0c49295ae6bb72c34ee31abbe611b", size = 7173206, upload-time = "2026-02-06T09:56:29.876Z" }, + { url = "https://files.pythonhosted.org/packages/df/1e/b8801345629a415ea7e26c83d75eb5dbe91b07ffe5210cc517348a8d4218/grpcio-1.78.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:be63c88b32e6c0f1429f1398ca5c09bc64b0d80950c8bb7807d7d7fb36fb84c7", size = 6693826, upload-time = "2026-02-06T09:56:32.305Z" }, + { url = "https://files.pythonhosted.org/packages/34/84/0de28eac0377742679a510784f049738a80424b17287739fc47d63c2439e/grpcio-1.78.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:3c586ac70e855c721bda8f548d38c3ca66ac791dc49b66a8281a1f99db85e452", size = 7277897, upload-time = "2026-02-06T09:56:34.915Z" }, + { url = "https://files.pythonhosted.org/packages/ca/9c/ad8685cfe20559a9edb66f735afdcb2b7d3de69b13666fdfc542e1916ebd/grpcio-1.78.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:35eb275bf1751d2ffbd8f57cdbc46058e857cf3971041521b78b7db94bdaf127", size = 8252404, upload-time = "2026-02-06T09:56:37.553Z" }, + { url = "https://files.pythonhosted.org/packages/3c/05/33a7a4985586f27e1de4803887c417ec7ced145ebd069bc38a9607059e2b/grpcio-1.78.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:207db540302c884b8848036b80db352a832b99dfdf41db1eb554c2c2c7800f65", size = 7696837, upload-time = "2026-02-06T09:56:40.173Z" }, + { url = "https://files.pythonhosted.org/packages/73/77/7382241caf88729b106e49e7d18e3116216c778e6a7e833826eb96de22f7/grpcio-1.78.0-cp314-cp314-win32.whl", hash = "sha256:57bab6deef2f4f1ca76cc04565df38dc5713ae6c17de690721bdf30cb1e0545c", size = 4142439, upload-time = "2026-02-06T09:56:43.258Z" }, + { url = "https://files.pythonhosted.org/packages/48/b2/b096ccce418882fbfda4f7496f9357aaa9a5af1896a9a7f60d9f2b275a06/grpcio-1.78.0-cp314-cp314-win_amd64.whl", hash = "sha256:dce09d6116df20a96acfdbf85e4866258c3758180e8c49845d6ba8248b6d0bbb", size = 4929852, upload-time = "2026-02-06T09:56:45.885Z" }, ] [[package]] @@ -2546,31 +2577,34 @@ wheels = [ [[package]] name = "hf-xet" -version = "1.3.0" +version = "1.3.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4f/3a/9aa61729228fb03e946409c51963f0cd2fd7c109f4ab93edc5f04a10be86/hf_xet-1.3.0.tar.gz", hash = "sha256:9c154ad63e17aca970987b2cf17dbd8a0c09bb18aeb246f637647a8058e4522b", size = 641390, upload-time = "2026-02-24T00:16:19.935Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/18/16954a87cfdfdc04792f1ffc9a29c0a48253ab10ec0f4856f39c7f7bf7cd/hf_xet-1.3.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:95bdeab4747cb45f855601e39b9e86ae92b4a114978ada6e0401961fcc5d2958", size = 3759481, upload-time = "2026-02-24T00:16:03.387Z" }, - { url = "https://files.pythonhosted.org/packages/d8/6f/a55752047e9b0e69517775531c14680331f00c9cd4dc07f5e9b7f7f68a12/hf_xet-1.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f99992583f27b139392601fe99e88df155dc4de7feba98ed27ce2d3e6b4a65bb", size = 3517927, upload-time = "2026-02-24T00:16:02.108Z" }, - { url = "https://files.pythonhosted.org/packages/ef/71/a909dbf9c8b166aa3f15db2bcf5d8afbe9d53170922edde2b919cf0bc455/hf_xet-1.3.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:687a71fc6d2eaa79d864da3aa13e5d887e124d357f5f306bfff6c385eea9d990", size = 4174328, upload-time = "2026-02-24T00:15:55.056Z" }, - { url = "https://files.pythonhosted.org/packages/21/cc/dec0d971bb5872345b8d64363a0b78ed6a147eea5b4281575ce5a8150f42/hf_xet-1.3.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:75d19813ed0e24525409bc22566282ae9bc93e5d764b185565e863dc28280a45", size = 3953184, upload-time = "2026-02-24T00:15:53.43Z" }, - { url = "https://files.pythonhosted.org/packages/3d/d8/d4259146e7c7089dd3f22cd62676d665bcfbc27428a070abee8985e0ab33/hf_xet-1.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:078af43569c2e05233137a93a33d2293f95c272745eaf030a9bb5f27bb0c9e9c", size = 4152800, upload-time = "2026-02-24T00:16:10.391Z" }, - { url = "https://files.pythonhosted.org/packages/c9/0d/39d9d32e4cde689da618739197e264bba5a55d870377d5d32cdd5c03fad8/hf_xet-1.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:be8731e1620cc8549025c39ed3917c8fd125efaeae54ae679214a3d573e6c109", size = 4390499, upload-time = "2026-02-24T00:16:11.671Z" }, - { url = "https://files.pythonhosted.org/packages/d9/27/5b9c323bf5513e8971702eeac43ba5cb554921e0f292ad52f20ed6028131/hf_xet-1.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:1552616c0e0fa728a4ffdffa106e91faa0fd4edb44868e79b464fad00b2758ee", size = 3634124, upload-time = "2026-02-24T00:16:20.964Z" }, - { url = "https://files.pythonhosted.org/packages/85/32/76949adb65b7ca54c1e2b0519a98f7c88221b9091ae8780fc76d7d1bae70/hf_xet-1.3.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:a61496eccf412d7c51a5613c31a2051d357ddea6be53a0672c7644cf39bfefe9", size = 3759780, upload-time = "2026-02-24T00:16:09.037Z" }, - { url = "https://files.pythonhosted.org/packages/63/c4/ad6fa712611711c129fa49eb17baaf0665647eb0abce32d94ccd44b69c6d/hf_xet-1.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:aba35218871cc438826076778958f7ab2a1f4f8d654e91c307073a815360558f", size = 3517640, upload-time = "2026-02-24T00:16:07.536Z" }, - { url = "https://files.pythonhosted.org/packages/15/6b/b44659c5261cde6320a579d0acc949f19283a13d32fc9389fc49639f435e/hf_xet-1.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c444d8f657dedd7a72aa0ef0178fe01fe92b04b58014ee49e2b3b4985aea1529", size = 4174285, upload-time = "2026-02-24T00:16:00.848Z" }, - { url = "https://files.pythonhosted.org/packages/61/cf/16ef1b366482fa4e71d1642b019158d7ac891bcb961477102ceadfe69436/hf_xet-1.3.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:6d1bbda7900d72bc591cd39a64e35ad07f89a24f90e3d7b7c692cb93a1926cde", size = 3952705, upload-time = "2026-02-24T00:15:59.355Z" }, - { url = "https://files.pythonhosted.org/packages/d5/5a/d03453902ab9373715f50f3969979782a355df94329ea958ae78304ca06b/hf_xet-1.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:588f5df302e7dba5c3b60d4e5c683f95678526c29b9f64cbeb23e9f1889c6b83", size = 4152353, upload-time = "2026-02-24T00:16:15.857Z" }, - { url = "https://files.pythonhosted.org/packages/ab/98/d3cd8cdd8d771bee9a03bd52faed6fa114a68a107a0e337aaf0b4c52bf0c/hf_xet-1.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:944ae454b296c42b18219c37f245c78d0e64a734057423e9309f4938faa85d7f", size = 4390010, upload-time = "2026-02-24T00:16:18.713Z" }, - { url = "https://files.pythonhosted.org/packages/1f/10/3c58501d44d7a148d749ffa6046cbd14aa75a7ab07c9e7a984f86294cc53/hf_xet-1.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:34cdd5f10e61b7a1a7542672d20887c85debcfeb70a471ff1506f5a4c9441e42", size = 3634277, upload-time = "2026-02-24T00:16:23.718Z" }, - { url = "https://files.pythonhosted.org/packages/a1/00/22d3d896466ded4c46ef6465b85fa434fa97d79f8f61cea322afde1d6157/hf_xet-1.3.0-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:df4447f69086dcc6418583315eda6ed09033ac1fbbc784fedcbbbdf67bea1680", size = 3761293, upload-time = "2026-02-24T00:16:06.012Z" }, - { url = "https://files.pythonhosted.org/packages/97/fd/ebb0ea49e9bd9eb9f52844e417e0e6e9c8a59a1e84790691873fa910adc5/hf_xet-1.3.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:39f4fe714628adc2214ab4a67391182ee751bc4db581868cb3204900817758a8", size = 3523345, upload-time = "2026-02-24T00:16:04.615Z" }, - { url = "https://files.pythonhosted.org/packages/8a/bb/72ceaaf619cad23d151a281d52e15456bae72f52c3795e820c0b64a5f637/hf_xet-1.3.0-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9b16e53ed6b5c8197cefb3fd12047a430b7034428effed463c03cec68de7e9a3", size = 4178623, upload-time = "2026-02-24T00:15:57.857Z" }, - { url = "https://files.pythonhosted.org/packages/19/30/3280f4b5e407b442923a80ac0b2d96a65be7494457c55695e63f9a2b33dd/hf_xet-1.3.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:92051a1f73019489be77f6837671024ec785a3d1b888466b09d3a9ea15c4a1b5", size = 3958884, upload-time = "2026-02-24T00:15:56.326Z" }, - { url = "https://files.pythonhosted.org/packages/8f/13/5174c6d52583e54a761c88570ca657d621ac684747613f47846debfd6d4d/hf_xet-1.3.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:943046b160e7804a85e68a659d2eee1a83ce3661f72d1294d3cc5ece0f45a355", size = 4158146, upload-time = "2026-02-24T00:16:13.158Z" }, - { url = "https://files.pythonhosted.org/packages/12/13/ea8619021b119e19efdcaeec72f762b5be923cf79b5d4434f2cbbff39829/hf_xet-1.3.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9b798a95d41b4f33b0b455c8aa76ff1fd26a587a4dd3bdec29f0a37c60b78a2f", size = 4395565, upload-time = "2026-02-24T00:16:14.574Z" }, - { url = "https://files.pythonhosted.org/packages/64/cd/b81d922118a171bfbbecffd60a477e79188ab876260412fac47226a685bf/hf_xet-1.3.0-cp37-abi3-win_amd64.whl", hash = "sha256:227eee5b99d19b9f20c31d901a0c2373af610a24a34e6c2701072c9de48d6d95", size = 3637830, upload-time = "2026-02-24T00:16:22.474Z" }, +sdist = { url = "https://files.pythonhosted.org/packages/8b/cb/9bb543bd987ffa1ee48202cc96a756951b734b79a542335c566148ade36c/hf_xet-1.3.2.tar.gz", hash = "sha256:e130ee08984783d12717444e538587fa2119385e5bd8fc2bb9f930419b73a7af", size = 643646, upload-time = "2026-02-27T17:26:08.051Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/75/462285971954269432aad2e7938c5c7ff9ec7d60129cec542ab37121e3d6/hf_xet-1.3.2-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:335a8f36c55fd35a92d0062f4e9201b4015057e62747b7e7001ffb203c0ee1d2", size = 3761019, upload-time = "2026-02-27T17:25:49.441Z" }, + { url = "https://files.pythonhosted.org/packages/35/56/987b0537ddaf88e17192ea09afa8eca853e55f39a4721578be436f8409df/hf_xet-1.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c1ae4d3a716afc774e66922f3cac8206bfa707db13f6a7e62dfff74bfc95c9a8", size = 3521565, upload-time = "2026-02-27T17:25:47.469Z" }, + { url = "https://files.pythonhosted.org/packages/a8/5c/7e4a33a3d689f77761156cc34558047569e54af92e4d15a8f493229f6767/hf_xet-1.3.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d6dbdf231efac0b9b39adcf12a07f0c030498f9212a18e8c50224d0e84ab803d", size = 4176494, upload-time = "2026-02-27T17:25:40.247Z" }, + { url = "https://files.pythonhosted.org/packages/6b/b3/71e856bf9d9a69b3931837e8bf22e095775f268c8edcd4a9e8c355f92484/hf_xet-1.3.2-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:c1980abfb68ecf6c1c7983379ed7b1e2b49a1aaf1a5aca9acc7d48e5e2e0a961", size = 3955601, upload-time = "2026-02-27T17:25:38.376Z" }, + { url = "https://files.pythonhosted.org/packages/63/d7/aecf97b3f0a981600a67ff4db15e2d433389d698a284bb0ea5d8fcdd6f7f/hf_xet-1.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1c88fbd90ad0d27c46b77a445f0a436ebaa94e14965c581123b68b1c52f5fd30", size = 4154770, upload-time = "2026-02-27T17:25:56.756Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e1/3af961f71a40e09bf5ee909842127b6b00f5ab4ee3817599dc0771b79893/hf_xet-1.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:35b855024ca37f2dd113ac1c08993e997fbe167b9d61f9ef66d3d4f84015e508", size = 4394161, upload-time = "2026-02-27T17:25:58.111Z" }, + { url = "https://files.pythonhosted.org/packages/a1/c3/859509bade9178e21b8b1db867b8e10e9f817ab9ac1de77cb9f461ced765/hf_xet-1.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:31612ba0629046e425ba50375685a2586e11fb9144270ebabd75878c3eaf6378", size = 3637377, upload-time = "2026-02-27T17:26:10.611Z" }, + { url = "https://files.pythonhosted.org/packages/05/7f/724cfbef4da92d577b71f68bf832961c8919f36c60d28d289a9fc9d024d4/hf_xet-1.3.2-cp313-cp313t-win_arm64.whl", hash = "sha256:433c77c9f4e132b562f37d66c9b22c05b5479f243a1f06a120c1c06ce8b1502a", size = 3497875, upload-time = "2026-02-27T17:26:09.034Z" }, + { url = "https://files.pythonhosted.org/packages/ba/75/9d54c1ae1d05fb704f977eca1671747babf1957f19f38ae75c5933bc2dc1/hf_xet-1.3.2-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:c34e2c7aefad15792d57067c1c89b2b02c1bbaeabd7f8456ae3d07b4bbaf4094", size = 3761076, upload-time = "2026-02-27T17:25:55.42Z" }, + { url = "https://files.pythonhosted.org/packages/f2/8a/08a24b6c6f52b5d26848c16e4b6d790bb810d1bf62c3505bed179f7032d3/hf_xet-1.3.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4bc995d6c41992831f762096020dc14a65fdf3963f86ffed580b596d04de32e3", size = 3521745, upload-time = "2026-02-27T17:25:54.217Z" }, + { url = "https://files.pythonhosted.org/packages/b5/db/a75cf400dd8a1a8acf226a12955ff6ee999f272dfc0505bafd8079a61267/hf_xet-1.3.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:959083c89dee30f7d6f890b36cdadda823386c4de63b1a30384a75bfd2ae995d", size = 4176301, upload-time = "2026-02-27T17:25:46.044Z" }, + { url = "https://files.pythonhosted.org/packages/01/40/6c4c798ffdd83e740dd3925c4e47793b07442a9efa3bc3866ba141a82365/hf_xet-1.3.2-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:cfa760888633b08c01b398d212ce7e8c0d7adac6c86e4b20dfb2397d8acd78ee", size = 3955437, upload-time = "2026-02-27T17:25:44.703Z" }, + { url = "https://files.pythonhosted.org/packages/0c/09/9a3aa7c5f07d3e5cc57bb750d12a124ffa72c273a87164bd848f9ac5cc14/hf_xet-1.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3155a02e083aa21fd733a7485c7c36025e49d5975c8d6bda0453d224dd0b0ac4", size = 4154535, upload-time = "2026-02-27T17:26:05.207Z" }, + { url = "https://files.pythonhosted.org/packages/ae/e0/831f7fa6d90cb47a230bc23284b502c700e1483bbe459437b3844cdc0776/hf_xet-1.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:91b1dc03c31cbf733d35dc03df7c5353686233d86af045e716f1e0ea4a2673cf", size = 4393891, upload-time = "2026-02-27T17:26:06.607Z" }, + { url = "https://files.pythonhosted.org/packages/ab/96/6ed472fdce7f8b70f5da6e3f05be76816a610063003bfd6d9cea0bbb58a3/hf_xet-1.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:211f30098512d95e85ad03ae63bd7dd2c4df476558a5095d09f9e38e78cbf674", size = 3637583, upload-time = "2026-02-27T17:26:17.349Z" }, + { url = "https://files.pythonhosted.org/packages/8b/e8/a069edc4570b3f8e123c0b80fadc94530f3d7b01394e1fc1bb223339366c/hf_xet-1.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:4a6817c41de7c48ed9270da0b02849347e089c5ece9a0e72ae4f4b3a57617f82", size = 3497977, upload-time = "2026-02-27T17:26:14.966Z" }, + { url = "https://files.pythonhosted.org/packages/d8/28/dbb024e2e3907f6f3052847ca7d1a2f7a3972fafcd53ff79018977fcb3e4/hf_xet-1.3.2-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:f93b7595f1d8fefddfede775c18b5c9256757824f7f6832930b49858483cd56f", size = 3763961, upload-time = "2026-02-27T17:25:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/e4/71/b99aed3823c9d1795e4865cf437d651097356a3f38c7d5877e4ac544b8e4/hf_xet-1.3.2-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:a85d3d43743174393afe27835bde0cd146e652b5fcfdbcd624602daef2ef3259", size = 3526171, upload-time = "2026-02-27T17:25:50.968Z" }, + { url = "https://files.pythonhosted.org/packages/9d/ca/907890ce6ef5598b5920514f255ed0a65f558f820515b18db75a51b2f878/hf_xet-1.3.2-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7c2a054a97c44e136b1f7f5a78f12b3efffdf2eed3abc6746fc5ea4b39511633", size = 4180750, upload-time = "2026-02-27T17:25:43.125Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ad/bc7f41f87173d51d0bce497b171c4ee0cbde1eed2d7b4216db5d0ada9f50/hf_xet-1.3.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:06b724a361f670ae557836e57801b82c75b534812e351a87a2c739f77d1e0635", size = 3961035, upload-time = "2026-02-27T17:25:41.837Z" }, + { url = "https://files.pythonhosted.org/packages/73/38/600f4dda40c4a33133404d9fe644f1d35ff2d9babb4d0435c646c63dd107/hf_xet-1.3.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:305f5489d7241a47e0458ef49334be02411d1d0f480846363c1c8084ed9916f7", size = 4161378, upload-time = "2026-02-27T17:26:00.365Z" }, + { url = "https://files.pythonhosted.org/packages/00/b3/7bc1ff91d1ac18420b7ad1e169b618b27c00001b96310a89f8a9294fe509/hf_xet-1.3.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:06cdbde243c85f39a63b28e9034321399c507bcd5e7befdd17ed2ccc06dfe14e", size = 4398020, upload-time = "2026-02-27T17:26:03.977Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0b/99bfd948a3ed3620ab709276df3ad3710dcea61976918cce8706502927af/hf_xet-1.3.2-cp37-abi3-win_amd64.whl", hash = "sha256:9298b47cce6037b7045ae41482e703c471ce36b52e73e49f71226d2e8e5685a1", size = 3641624, upload-time = "2026-02-27T17:26:13.542Z" }, + { url = "https://files.pythonhosted.org/packages/cc/02/9a6e4ca1f3f73a164c0cd48e41b3cc56585dcc37e809250de443d673266f/hf_xet-1.3.2-cp37-abi3-win_arm64.whl", hash = "sha256:83d8ec273136171431833a6957e8f3af496bee227a0fe47c7b8b39c106d1749a", size = 3503976, upload-time = "2026-02-27T17:26:12.123Z" }, ] [[package]] @@ -2635,7 +2669,7 @@ wheels = [ [[package]] name = "huggingface-hub" -version = "1.4.1" +version = "1.5.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "filelock", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -2644,14 +2678,13 @@ dependencies = [ { name = "httpx", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "packaging", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "shellingham", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "tqdm", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, - { name = "typer-slim", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "typer", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c4/fc/eb9bc06130e8bbda6a616e1b80a7aa127681c448d6b49806f61db2670b61/huggingface_hub-1.4.1.tar.gz", hash = "sha256:b41131ec35e631e7383ab26d6146b8d8972abc8b6309b963b306fbcca87f5ed5", size = 642156, upload-time = "2026-02-06T09:20:03.013Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/76/b5efb3033d8499b17f9386beaf60f64c461798e1ee16d10bc9c0077beba5/huggingface_hub-1.5.0.tar.gz", hash = "sha256:f281838db29265880fb543de7a23b0f81d3504675de82044307ea3c6c62f799d", size = 695872, upload-time = "2026-02-26T15:35:32.745Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/ae/2f6d96b4e6c5478d87d606a1934b5d436c4a2bce6bb7c6fdece891c128e3/huggingface_hub-1.4.1-py3-none-any.whl", hash = "sha256:9931d075fb7a79af5abc487106414ec5fba2c0ae86104c0c62fd6cae38873d18", size = 553326, upload-time = "2026-02-06T09:20:00.728Z" }, + { url = "https://files.pythonhosted.org/packages/ec/74/2bc951622e2dbba1af9a460d93c51d15e458becd486e62c29cc0ccb08178/huggingface_hub-1.5.0-py3-none-any.whl", hash = "sha256:c9c0b3ab95a777fc91666111f3b3ede71c0cdced3614c553a64e98920585c4ee", size = 596261, upload-time = "2026-02-26T15:35:31.1Z" }, ] [[package]] @@ -3087,7 +3120,7 @@ wheels = [ [[package]] name = "litellm" -version = "1.81.15" +version = "1.81.16" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -3103,9 +3136,9 @@ dependencies = [ { name = "tiktoken", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "tokenizers", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/70/0c/62a0fdc5adae6d205338f9239175aa6a93818e58b75cf000a9c7214a3d9f/litellm-1.81.15.tar.gz", hash = "sha256:a8a6277a53280762051c5818ebc76dd5f036368b9426c6f21795ae7f1ac6ebdc", size = 16597039, upload-time = "2026-02-24T06:52:50.892Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/36/3cbb22d6ef88c10f3fa4f04664c2a37e93a2e6f9c51899cd9fd025cb0a50/litellm-1.81.16.tar.gz", hash = "sha256:264a3868942e722cd6c19c2d625524fe624a1b6961c37c22d299dc7ea99823b3", size = 16668405, upload-time = "2026-02-26T13:01:48.429Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/fd/da11826dda0d332e360b9ead6c0c992d612ecb85b00df494823843cfcda3/litellm-1.81.15-py3-none-any.whl", hash = "sha256:2fa253658702509ce09fe0e172e5a47baaadf697fb0f784c7fd4ff665ae76ae1", size = 14682123, upload-time = "2026-02-24T06:52:48.084Z" }, + { url = "https://files.pythonhosted.org/packages/1f/1e/0022cde913bac87a493e4a182b8768f75e7ae90b64d4e11acb009b18311f/litellm-1.81.16-py3-none-any.whl", hash = "sha256:d6bcc13acbd26719e07bfa6b9923740e88409cbf1f9d626d85fc9ae0e0eec88c", size = 14774277, upload-time = "2026-02-26T13:01:45.652Z" }, ] [package.optional-dependencies] @@ -3148,11 +3181,11 @@ wheels = [ [[package]] name = "litellm-proxy-extras" -version = "0.4.47" +version = "0.4.48" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1e/e6/f4b7929116d7765e2983223a76f77ba7d597fcb4d7ba7a2cd5632037f7dd/litellm_proxy_extras-0.4.47.tar.gz", hash = "sha256:42d88929f9eaf0b827046d3712095354db843c1716ccabb2a40c806ea5f809b9", size = 28010, upload-time = "2026-02-24T03:31:11.446Z" } +sdist = { url = "https://files.pythonhosted.org/packages/08/69/ec88e8d951f59720091f22f65e79d92bc4d13f9eb4b1c223c855d7c38437/litellm_proxy_extras-0.4.48.tar.gz", hash = "sha256:5d5d8acf31b92d0cd6738555fb4a2411819755155438de9fb23c724c356400a2", size = 28657, upload-time = "2026-02-25T20:08:31.03Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/6d/f147ff929f2079fdda10ff461816679c4cc18d49495cce3c0ef658696a91/litellm_proxy_extras-0.4.47-py3-none-any.whl", hash = "sha256:2e900ae3edfbc20d27556f092d914974d37bac213efe88b8fd5287f77b2b7ca7", size = 63670, upload-time = "2026-02-24T03:31:13.047Z" }, + { url = "https://files.pythonhosted.org/packages/4a/22/7ee216638ede46fd2a09b9655ae4b0a0eb3987b79855f748f70c64ea5f67/litellm_proxy_extras-0.4.48-py3-none-any.whl", hash = "sha256:097001fccec5dbf4cffd902114898a9cfeba62673202447d55d2d0286cf93126", size = 65185, upload-time = "2026-02-25T20:08:30.073Z" }, ] [[package]] @@ -3932,7 +3965,7 @@ wheels = [ [[package]] name = "openai-agents" -version = "0.10.1" +version = "0.10.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffe", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -3943,9 +3976,9 @@ dependencies = [ { name = "types-requests", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/15/2c/a58fefef46bba20f5d8760509aebbe2a581d6ceb11f2ec56345e52b1d85d/openai_agents-0.10.1.tar.gz", hash = "sha256:41c5ae9f1f6e5c23826745ff99dc59a313929d9ddf8f451ac20d7d5dd47627ea", size = 2425265, upload-time = "2026-02-24T01:49:25.901Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4b/8f/21c2be52daefb8adeb6649ffcbee8bac6e8e22be05afd832d70876b085c4/openai_agents-0.10.2.tar.gz", hash = "sha256:195b0d81bb0f4b142c4b9153f2a54c1d332ca024a03e8e24b945f1cff8532ebd", size = 2439958, upload-time = "2026-02-26T08:06:45.942Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d0/7c/69e94f7580c6fb999c26bec9a680e94e76db66460438c8ece0b09b898d1b/openai_agents-0.10.1-py3-none-any.whl", hash = "sha256:12b3295d7b240533060032e625bef472a07761f5eef732412e30bd82f4c14945", size = 400624, upload-time = "2026-02-24T01:49:23.561Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2c/6c5c607da44307e49f3107be307a794eea9245e1fac9e666e7d522e866d4/openai_agents-0.10.2-py3-none-any.whl", hash = "sha256:8bf8bbd16cdba02e9c63c193ff2811b09d7094c5c39a4e2daa49a7037b840bc1", size = 404190, upload-time = "2026-02-26T08:06:43.952Z" }, ] [[package]] @@ -4009,7 +4042,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "googleapis-common-protos", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "grpcio", version = "1.67.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.14' and sys_platform == 'darwin') or (python_full_version < '3.14' and sys_platform == 'linux') or (python_full_version < '3.14' and sys_platform == 'win32')" }, - { name = "grpcio", version = "1.78.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.14' and sys_platform == 'darwin') or (python_full_version >= '3.14' and sys_platform == 'linux') or (python_full_version >= '3.14' and sys_platform == 'win32')" }, + { name = "grpcio", version = "1.78.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.14' and sys_platform == 'darwin') or (python_full_version >= '3.14' and sys_platform == 'linux') or (python_full_version >= '3.14' and sys_platform == 'win32')" }, { name = "opentelemetry-api", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "opentelemetry-exporter-otlp-proto-common", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "opentelemetry-proto", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -4515,16 +4548,16 @@ wheels = [ [[package]] name = "poethepoet" -version = "0.42.0" +version = "0.42.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pastel", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "pyyaml", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "tomli", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4a/9a/4e81fafef2ba94e5c974b4701343d1f053a27575ab5133cbd264348925dd/poethepoet-0.42.0.tar.gz", hash = "sha256:c9a2828259e585e9ed152857602130ff339f7b1638879b80d4a23f25588be4f8", size = 91278, upload-time = "2026-02-22T14:24:50.967Z" } +sdist = { url = "https://files.pythonhosted.org/packages/05/9b/e717572686bbf23e17483389c1bf3a381ca2427c84c7e0af0cdc0f23fccc/poethepoet-0.42.1.tar.gz", hash = "sha256:205747e276062c2aaba8afd8a98838f8a3a0237b7ab94715fab8d82718aac14f", size = 93209, upload-time = "2026-02-26T22:57:50.883Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f1/3e/58041b7e4d49b69e859dc81c35e221cf02d91ed4dbb5a2f6cc4698a29f44/poethepoet-0.42.0-py3-none-any.whl", hash = "sha256:e43cc20d458ee5bfccaa4572bc5783bcb93991a7d2fcf8dadc9c43f1ebc9b277", size = 118091, upload-time = "2026-02-22T14:24:49.53Z" }, + { url = "https://files.pythonhosted.org/packages/c8/68/75fa0a5ef39718ea6ba7ab6a3d031fa93640e57585580cec85539540bb65/poethepoet-0.42.1-py3-none-any.whl", hash = "sha256:d8d1345a5ca521be9255e7c13bc2c4c8698ed5e5ac5e9e94890d239fcd423d0a", size = 119967, upload-time = "2026-02-26T22:57:49.467Z" }, ] [[package]] @@ -4569,7 +4602,7 @@ wheels = [ [[package]] name = "posthog" -version = "7.9.3" +version = "7.9.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "backoff", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -4579,9 +4612,9 @@ dependencies = [ { name = "six", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/7e/06/bcffcd262c861695fbaa74490b872e37d6fc41d3dcc1a43207d20525522f/posthog-7.9.3.tar.gz", hash = "sha256:55f7580265d290936ac4c112a4e2031a41743be4f90d4183ac9f85b721ff13ae", size = 172336, upload-time = "2026-02-18T22:20:24.085Z" } +sdist = { url = "https://files.pythonhosted.org/packages/55/50/5c0d9232118fdc1434c1b7bbc1a14de5b310498ede09a7e2123ae1f5f8bd/posthog-7.9.4.tar.gz", hash = "sha256:50acc94ef6267d7030575d2ff54e89e748fac2e98525ac672aeb0423160f77cf", size = 172973, upload-time = "2026-02-25T15:28:47.065Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/11/7e/0e06a96823fa7c11ce73920e6ff77e82445db62ac4eae0b6f211edb4c4c2/posthog-7.9.3-py3-none-any.whl", hash = "sha256:2ddcacdef6c4afb124ebfcf27d7be58388943a7e24f8d4a51a52732c9b90bad6", size = 197819, upload-time = "2026-02-18T22:20:22.015Z" }, + { url = "https://files.pythonhosted.org/packages/df/6f/794a4e94e3640282e75013ce18e65f0a01afc8d71f733664b4a272f98bce/posthog-7.9.4-py3-none-any.whl", hash = "sha256:414125ddd7a48b9c67feb24d723df1f666af41ad10f8a9a8bbaf5e3b536a2e26", size = 198651, upload-time = "2026-02-25T15:28:45.398Z" }, ] [[package]] @@ -4589,8 +4622,8 @@ name = "powerfx" version = "0.0.34" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "cffi", marker = "(python_full_version < '3.14' and sys_platform == 'darwin') or (python_full_version < '3.14' and sys_platform == 'linux') or (python_full_version < '3.14' and sys_platform == 'win32')" }, - { name = "pythonnet", marker = "(python_full_version < '3.14' and sys_platform == 'darwin') or (python_full_version < '3.14' and sys_platform == 'linux') or (python_full_version < '3.14' and sys_platform == 'win32')" }, + { name = "cffi", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, + { name = "pythonnet", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9f/fb/6c4bf87e0c74ca1c563921ce89ca1c5785b7576bca932f7255cdf81082a7/powerfx-0.0.34.tar.gz", hash = "sha256:956992e7afd272657ed16d80f4cad24ec95d9e4a79fb9dfa4a068a09e136af32", size = 3237555, upload-time = "2025-12-22T15:50:59.682Z" } wheels = [ @@ -5253,7 +5286,7 @@ name = "pythonnet" version = "3.0.5" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "clr-loader", marker = "(python_full_version < '3.14' and sys_platform == 'darwin') or (python_full_version < '3.14' and sys_platform == 'linux') or (python_full_version < '3.14' and sys_platform == 'win32')" }, + { name = "clr-loader", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9a/d6/1afd75edd932306ae9bd2c2d961d603dc2b52fcec51b04afea464f1f6646/pythonnet-3.0.5.tar.gz", hash = "sha256:48e43ca463941b3608b32b4e236db92d8d40db4c58a75ace902985f76dac21cf", size = 239212, upload-time = "2024-12-13T08:30:44.393Z" } wheels = [ @@ -5361,7 +5394,7 @@ version = "1.17.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "grpcio", version = "1.67.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.14' and sys_platform == 'darwin') or (python_full_version < '3.14' and sys_platform == 'linux') or (python_full_version < '3.14' and sys_platform == 'win32')" }, - { name = "grpcio", version = "1.78.1", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.14' and sys_platform == 'darwin') or (python_full_version >= '3.14' and sys_platform == 'linux') or (python_full_version >= '3.14' and sys_platform == 'win32')" }, + { name = "grpcio", version = "1.78.0", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.14' and sys_platform == 'darwin') or (python_full_version >= '3.14' and sys_platform == 'linux') or (python_full_version >= '3.14' and sys_platform == 'win32')" }, { name = "httpx", extra = ["http2"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" }, { name = "numpy", version = "2.4.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.11' and sys_platform == 'darwin') or (python_full_version >= '3.11' and sys_platform == 'linux') or (python_full_version >= '3.11' and sys_platform == 'win32')" }, @@ -5389,7 +5422,7 @@ wheels = [ [[package]] name = "redisvl" -version = "0.14.0" +version = "0.15.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jsonpath-ng", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, @@ -5402,9 +5435,9 @@ dependencies = [ { name = "redis", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, { name = "tenacity", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/21/45/1c5b308f68b01c4e33590a8e1445f43c51292917b28c2def8deaa5b3dc5b/redisvl-0.14.0.tar.gz", hash = "sha256:7a84c46858dbc86943e64ffe8590013684d03d79b72a634d10c02ce5d1c02335", size = 759829, upload-time = "2026-02-06T15:48:19.384Z" } +sdist = { url = "https://files.pythonhosted.org/packages/72/1a/f1f0ff963622c34a9e9a9f2a0c6ad82bfbd05c082ecc89e38e092e3e9069/redisvl-0.15.0.tar.gz", hash = "sha256:0e382e9b6cd8378dfe1515b18f92d125cfba905f6f3c5fe9b8904b3ca840d1ca", size = 861480, upload-time = "2026-02-27T14:02:33.366Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/24/e9/264455caf42501b2b0747ac4819c7d0a2b458fad5e4e1f7610b6383d6d74/redisvl-0.14.0-py3-none-any.whl", hash = "sha256:85ec38f414427260da82ef20653a62d4c2626b97672c5c950616e5dde3cf0d0b", size = 196705, upload-time = "2026-02-06T15:48:17.636Z" }, + { url = "https://files.pythonhosted.org/packages/cc/23/5c5263a3cfc66957fa3bb154ef9441fbbcfb2f4eae910eb18e316db168b1/redisvl-0.15.0-py3-none-any.whl", hash = "sha256:aff716b9a9c4aef9c81de9a12d9939a0170ff3b3a1fe9d4164e94b131a754290", size = 197935, upload-time = "2026-02-27T14:02:31.262Z" }, ] [[package]] @@ -5720,27 +5753,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/06/04/eab13a954e763b0606f460443fcbf6bb5a0faf06890ea3754ff16523dce5/ruff-0.15.2.tar.gz", hash = "sha256:14b965afee0969e68bb871eba625343b8673375f457af4abe98553e8bbb98342", size = 4558148, upload-time = "2026-02-19T22:32:20.271Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/70/3a4dc6d09b13cb3e695f28307e5d889b2e1a66b7af9c5e257e796695b0e6/ruff-0.15.2-py3-none-linux_armv6l.whl", hash = "sha256:120691a6fdae2f16d65435648160f5b81a9625288f75544dc40637436b5d3c0d", size = 10430565, upload-time = "2026-02-19T22:32:41.824Z" }, - { url = "https://files.pythonhosted.org/packages/71/0b/bb8457b56185ece1305c666dc895832946d24055be90692381c31d57466d/ruff-0.15.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a89056d831256099658b6bba4037ac6dd06f49d194199215befe2bb10457ea5e", size = 10820354, upload-time = "2026-02-19T22:32:07.366Z" }, - { url = "https://files.pythonhosted.org/packages/2d/c1/e0532d7f9c9e0b14c46f61b14afd563298b8b83f337b6789ddd987e46121/ruff-0.15.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e36dee3a64be0ebd23c86ffa3aa3fd3ac9a712ff295e192243f814a830b6bd87", size = 10170767, upload-time = "2026-02-19T22:32:13.188Z" }, - { url = "https://files.pythonhosted.org/packages/47/e8/da1aa341d3af017a21c7a62fb5ec31d4e7ad0a93ab80e3a508316efbcb23/ruff-0.15.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9fb47b6d9764677f8c0a193c0943ce9a05d6763523f132325af8a858eadc2b9", size = 10529591, upload-time = "2026-02-19T22:32:02.547Z" }, - { url = "https://files.pythonhosted.org/packages/93/74/184fbf38e9f3510231fbc5e437e808f0b48c42d1df9434b208821efcd8d6/ruff-0.15.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f376990f9d0d6442ea9014b19621d8f2aaf2b8e39fdbfc79220b7f0c596c9b80", size = 10260771, upload-time = "2026-02-19T22:32:36.938Z" }, - { url = "https://files.pythonhosted.org/packages/05/ac/605c20b8e059a0bc4b42360414baa4892ff278cec1c91fff4be0dceedefd/ruff-0.15.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2dcc987551952d73cbf5c88d9fdee815618d497e4df86cd4c4824cc59d5dd75f", size = 11045791, upload-time = "2026-02-19T22:32:31.642Z" }, - { url = "https://files.pythonhosted.org/packages/fd/52/db6e419908f45a894924d410ac77d64bdd98ff86901d833364251bd08e22/ruff-0.15.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42a47fd785cbe8c01b9ff45031af875d101b040ad8f4de7bbb716487c74c9a77", size = 11879271, upload-time = "2026-02-19T22:32:29.305Z" }, - { url = "https://files.pythonhosted.org/packages/3e/d8/7992b18f2008bdc9231d0f10b16df7dda964dbf639e2b8b4c1b4e91b83af/ruff-0.15.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbe9f49354866e575b4c6943856989f966421870e85cd2ac94dccb0a9dcb2fea", size = 11303707, upload-time = "2026-02-19T22:32:22.492Z" }, - { url = "https://files.pythonhosted.org/packages/d7/02/849b46184bcfdd4b64cde61752cc9a146c54759ed036edd11857e9b8443b/ruff-0.15.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7a672c82b5f9887576087d97be5ce439f04bbaf548ee987b92d3a7dede41d3a", size = 11149151, upload-time = "2026-02-19T22:32:44.234Z" }, - { url = "https://files.pythonhosted.org/packages/70/04/f5284e388bab60d1d3b99614a5a9aeb03e0f333847e2429bebd2aaa1feec/ruff-0.15.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:72ecc64f46f7019e2bcc3cdc05d4a7da958b629a5ab7033195e11a438403d956", size = 11091132, upload-time = "2026-02-19T22:32:24.691Z" }, - { url = "https://files.pythonhosted.org/packages/fa/ae/88d844a21110e14d92cf73d57363fab59b727ebeabe78009b9ccb23500af/ruff-0.15.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:8dcf243b15b561c655c1ef2f2b0050e5d50db37fe90115507f6ff37d865dc8b4", size = 10504717, upload-time = "2026-02-19T22:32:26.75Z" }, - { url = "https://files.pythonhosted.org/packages/64/27/867076a6ada7f2b9c8292884ab44d08fd2ba71bd2b5364d4136f3cd537e1/ruff-0.15.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dab6941c862c05739774677c6273166d2510d254dac0695c0e3f5efa1b5585de", size = 10263122, upload-time = "2026-02-19T22:32:10.036Z" }, - { url = "https://files.pythonhosted.org/packages/e7/ef/faf9321d550f8ebf0c6373696e70d1758e20ccdc3951ad7af00c0956be7c/ruff-0.15.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1b9164f57fc36058e9a6806eb92af185b0697c9fe4c7c52caa431c6554521e5c", size = 10735295, upload-time = "2026-02-19T22:32:39.227Z" }, - { url = "https://files.pythonhosted.org/packages/2f/55/e8089fec62e050ba84d71b70e7834b97709ca9b7aba10c1a0b196e493f97/ruff-0.15.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:80d24fcae24d42659db7e335b9e1531697a7102c19185b8dc4a028b952865fd8", size = 11241641, upload-time = "2026-02-19T22:32:34.617Z" }, - { url = "https://files.pythonhosted.org/packages/23/01/1c30526460f4d23222d0fabd5888868262fd0e2b71a00570ca26483cd993/ruff-0.15.2-py3-none-win32.whl", hash = "sha256:fd5ff9e5f519a7e1bd99cbe8daa324010a74f5e2ebc97c6242c08f26f3714f6f", size = 10507885, upload-time = "2026-02-19T22:32:15.635Z" }, - { url = "https://files.pythonhosted.org/packages/5c/10/3d18e3bbdf8fc50bbb4ac3cc45970aa5a9753c5cb51bf9ed9a3cd8b79fa3/ruff-0.15.2-py3-none-win_amd64.whl", hash = "sha256:d20014e3dfa400f3ff84830dfb5755ece2de45ab62ecea4af6b7262d0fb4f7c5", size = 11623725, upload-time = "2026-02-19T22:32:04.947Z" }, - { url = "https://files.pythonhosted.org/packages/6d/78/097c0798b1dab9f8affe73da9642bb4500e098cb27fd8dc9724816ac747b/ruff-0.15.2-py3-none-win_arm64.whl", hash = "sha256:cabddc5822acdc8f7b5527b36ceac55cc51eec7b1946e60181de8fe83ca8876e", size = 10941649, upload-time = "2026-02-19T22:32:18.108Z" }, +version = "0.15.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/31/d6e536cdebb6568ae75a7f00e4b4819ae0ad2640c3604c305a0428680b0c/ruff-0.15.4.tar.gz", hash = "sha256:3412195319e42d634470cc97aa9803d07e9d5c9223b99bcb1518f0c725f26ae1", size = 4569550, upload-time = "2026-02-26T20:04:14.959Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f2/82/c11a03cfec3a4d26a0ea1e571f0f44be5993b923f905eeddfc397c13d360/ruff-0.15.4-py3-none-linux_armv6l.whl", hash = "sha256:a1810931c41606c686bae8b5b9a8072adac2f611bb433c0ba476acba17a332e0", size = 10453333, upload-time = "2026-02-26T20:04:20.093Z" }, + { url = "https://files.pythonhosted.org/packages/ce/5d/6a1f271f6e31dffb31855996493641edc3eef8077b883eaf007a2f1c2976/ruff-0.15.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5a1632c66672b8b4d3e1d1782859e98d6e0b4e70829530666644286600a33992", size = 10853356, upload-time = "2026-02-26T20:04:05.808Z" }, + { url = "https://files.pythonhosted.org/packages/b1/d8/0fab9f8842b83b1a9c2bf81b85063f65e93fb512e60effa95b0be49bfc54/ruff-0.15.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a4386ba2cd6c0f4ff75252845906acc7c7c8e1ac567b7bc3d373686ac8c222ba", size = 10187434, upload-time = "2026-02-26T20:03:54.656Z" }, + { url = "https://files.pythonhosted.org/packages/85/cc/cc220fd9394eff5db8d94dec199eec56dd6c9f3651d8869d024867a91030/ruff-0.15.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2496488bdfd3732747558b6f95ae427ff066d1fcd054daf75f5a50674411e75", size = 10535456, upload-time = "2026-02-26T20:03:52.738Z" }, + { url = "https://files.pythonhosted.org/packages/fa/0f/bced38fa5cf24373ec767713c8e4cadc90247f3863605fb030e597878661/ruff-0.15.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3f1c4893841ff2d54cbda1b2860fa3260173df5ddd7b95d370186f8a5e66a4ac", size = 10287772, upload-time = "2026-02-26T20:04:08.138Z" }, + { url = "https://files.pythonhosted.org/packages/2b/90/58a1802d84fed15f8f281925b21ab3cecd813bde52a8ca033a4de8ab0e7a/ruff-0.15.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:820b8766bd65503b6c30aaa6331e8ef3a6e564f7999c844e9a547c40179e440a", size = 11049051, upload-time = "2026-02-26T20:04:03.53Z" }, + { url = "https://files.pythonhosted.org/packages/d2/ac/b7ad36703c35f3866584564dc15f12f91cb1a26a897dc2fd13d7cb3ae1af/ruff-0.15.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9fb74bab47139c1751f900f857fa503987253c3ef89129b24ed375e72873e85", size = 11890494, upload-time = "2026-02-26T20:04:10.497Z" }, + { url = "https://files.pythonhosted.org/packages/93/3d/3eb2f47a39a8b0da99faf9c54d3eb24720add1e886a5309d4d1be73a6380/ruff-0.15.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f80c98765949c518142b3a50a5db89343aa90f2c2bf7799de9986498ae6176db", size = 11326221, upload-time = "2026-02-26T20:04:12.84Z" }, + { url = "https://files.pythonhosted.org/packages/ff/90/bf134f4c1e5243e62690e09d63c55df948a74084c8ac3e48a88468314da6/ruff-0.15.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451a2e224151729b3b6c9ffb36aed9091b2996fe4bdbd11f47e27d8f2e8888ec", size = 11168459, upload-time = "2026-02-26T20:04:00.969Z" }, + { url = "https://files.pythonhosted.org/packages/b5/e5/a64d27688789b06b5d55162aafc32059bb8c989c61a5139a36e1368285eb/ruff-0.15.4-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a8f157f2e583c513c4f5f896163a93198297371f34c04220daf40d133fdd4f7f", size = 11104366, upload-time = "2026-02-26T20:03:48.099Z" }, + { url = "https://files.pythonhosted.org/packages/f1/f6/32d1dcb66a2559763fc3027bdd65836cad9eb09d90f2ed6a63d8e9252b02/ruff-0.15.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:917cc68503357021f541e69b35361c99387cdbbf99bd0ea4aa6f28ca99ff5338", size = 10510887, upload-time = "2026-02-26T20:03:45.771Z" }, + { url = "https://files.pythonhosted.org/packages/ff/92/22d1ced50971c5b6433aed166fcef8c9343f567a94cf2b9d9089f6aa80fe/ruff-0.15.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e9737c8161da79fd7cfec19f1e35620375bd8b2a50c3e77fa3d2c16f574105cc", size = 10285939, upload-time = "2026-02-26T20:04:22.42Z" }, + { url = "https://files.pythonhosted.org/packages/e6/f4/7c20aec3143837641a02509a4668fb146a642fd1211846634edc17eb5563/ruff-0.15.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:291258c917539e18f6ba40482fe31d6f5ac023994ee11d7bdafd716f2aab8a68", size = 10765471, upload-time = "2026-02-26T20:03:58.924Z" }, + { url = "https://files.pythonhosted.org/packages/d0/09/6d2f7586f09a16120aebdff8f64d962d7c4348313c77ebb29c566cefc357/ruff-0.15.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3f83c45911da6f2cd5936c436cf86b9f09f09165f033a99dcf7477e34041cbc3", size = 11263382, upload-time = "2026-02-26T20:04:24.424Z" }, + { url = "https://files.pythonhosted.org/packages/1b/fa/2ef715a1cd329ef47c1a050e10dee91a9054b7ce2fcfdd6a06d139afb7ec/ruff-0.15.4-py3-none-win32.whl", hash = "sha256:65594a2d557d4ee9f02834fcdf0a28daa8b3b9f6cb2cb93846025a36db47ef22", size = 10506664, upload-time = "2026-02-26T20:03:50.56Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a8/c688ef7e29983976820d18710f955751d9f4d4eb69df658af3d006e2ba3e/ruff-0.15.4-py3-none-win_amd64.whl", hash = "sha256:04196ad44f0df220c2ece5b0e959c2f37c777375ec744397d21d15b50a75264f", size = 11651048, upload-time = "2026-02-26T20:04:17.191Z" }, + { url = "https://files.pythonhosted.org/packages/3e/0a/9e1be9035b37448ce2e68c978f0591da94389ade5a5abafa4cf99985d1b2/ruff-0.15.4-py3-none-win_arm64.whl", hash = "sha256:60d5177e8cfc70e51b9c5fad936c634872a74209f934c1e79107d11787ad5453", size = 10966776, upload-time = "2026-02-26T20:03:56.908Z" }, ] [[package]] @@ -6526,18 +6559,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4a/91/48db081e7a63bb37284f9fbcefda7c44c277b18b0e13fbc36ea2335b71e6/typer-0.24.1-py3-none-any.whl", hash = "sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e", size = 56085, upload-time = "2026-02-21T16:54:41.616Z" }, ] -[[package]] -name = "typer-slim" -version = "0.24.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typer", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a7/a7/e6aecc4b4eb59598829a3b5076a93aff291b4fdaa2ded25efc4e1f4d219c/typer_slim-0.24.0.tar.gz", hash = "sha256:f0ed36127183f52ae6ced2ecb2521789995992c521a46083bfcdbb652d22ad34", size = 4776, upload-time = "2026-02-16T22:08:51.2Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/24/5480c20380dfd18cf33d14784096dca45a24eae6102e91d49a718d3b6855/typer_slim-0.24.0-py3-none-any.whl", hash = "sha256:d5d7ee1ee2834d5020c7c616ed5e0d0f29b9a4b1dd283bdebae198ec09778d0e", size = 3394, upload-time = "2026-02-16T22:08:49.92Z" }, -] - [[package]] name = "types-python-dateutil" version = "2.9.0.20260124" @@ -6621,27 +6642,27 @@ wheels = [ [[package]] name = "uv" -version = "0.10.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/90/2f/472ff992c50e5947ef0570d291cfa3a70b423e5dcc6bee99b7a8e7b6da49/uv-0.10.5.tar.gz", hash = "sha256:c45de48b7fa6dd034de8515a7d129f85f4e74080b9f09a7bfc0bcce2798f8023", size = 3919437, upload-time = "2026-02-24T00:55:11.392Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/35/01/1521344a015f7fc01198f9d8560838adbeb9e80b835a23c25c712d8a8c08/uv-0.10.5-py3-none-linux_armv6l.whl", hash = "sha256:d1ccf2e7cf08b8a1477195da50476fb645bf20907072a39074f482049056aa5d", size = 22401966, upload-time = "2026-02-24T00:55:09.111Z" }, - { url = "https://files.pythonhosted.org/packages/3e/47/b4a4690f13d44f110ba7534a950a6ca63f61cc3d81c28f9c81afa9b74634/uv-0.10.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:63435e86321993dd5d90f440524f3f1b874b34aab30b7bf6752b48497117bfc4", size = 21504807, upload-time = "2026-02-24T00:55:18.55Z" }, - { url = "https://files.pythonhosted.org/packages/61/58/28725e2d223b36812f692123934c1cbd7a6bc5261d6cf0f3850889768c66/uv-0.10.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2cec424513140aa179d1c4decfcf86201497df7bc5674c13a20882d3b2837c7e", size = 20194774, upload-time = "2026-02-24T00:54:49.789Z" }, - { url = "https://files.pythonhosted.org/packages/6b/d4/87113bce59b9711e55995d2db66faffdb98952e371eab2d44fe4b0d79bf7/uv-0.10.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:3aa708beef7fab912d115ba1ccaad383a7006dc1a8e5ecdd9656574188221a84", size = 22044475, upload-time = "2026-02-24T00:54:56.924Z" }, - { url = "https://files.pythonhosted.org/packages/7b/2c/af72b186786c4dd9a3d71d747cd0e02868b6eb7836b29c51e0d4cfe649de/uv-0.10.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:74c6d2d38160bbb2d596560f27875c3906c0e94e61c6279b5111d3f2d74dbcd9", size = 22038345, upload-time = "2026-02-24T00:54:59.245Z" }, - { url = "https://files.pythonhosted.org/packages/61/8f/573edcdffe160093ef640b34690f13a2c6f35e03674fe52207bd9f63f23c/uv-0.10.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f3ff5bab65eb305d1cf024c5eb091b12f3d7b40e5a78409fb0afb937b2614001", size = 22006975, upload-time = "2026-02-24T00:55:28.954Z" }, - { url = "https://files.pythonhosted.org/packages/f0/28/9dbad27f80cc6b162f41c3becf154a1ba54177957ead4ae4faf3125b526f/uv-0.10.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd263e573a5259e6ce9854698e0c31e8ebdaa0a8d0701943db159854bbd6dcdf", size = 23326569, upload-time = "2026-02-24T00:55:33.966Z" }, - { url = "https://files.pythonhosted.org/packages/1d/a0/f5ee404b9601bfb03d36241637d0d2ff1089115e532bcd77de0d29a0a89b/uv-0.10.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:faaa30c94ffeda248c29b7185ce4d5809de4c54f2a1c16f0120d50564473d9b4", size = 24197070, upload-time = "2026-02-24T00:55:06.621Z" }, - { url = "https://files.pythonhosted.org/packages/dc/e8/c0c33168ca17f582727d33e629fa1673bc1e1c2411b174f2f78c1d16d287/uv-0.10.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49db2d27555d6f7c69422d2d5f79ebe2dc4ed6a859a698d015d48de51e16aaab", size = 23277854, upload-time = "2026-02-24T00:55:31.444Z" }, - { url = "https://files.pythonhosted.org/packages/8f/d9/4bb264bdb7f2e95efe09622cc6512288a842956bb4c2c3d6fe711eaef7df/uv-0.10.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8acf9be268ce2fc2c16117b5884f0724498d7191f8db2d12d8a7c7482652d38", size = 23252223, upload-time = "2026-02-24T00:55:16.256Z" }, - { url = "https://files.pythonhosted.org/packages/fc/ac/b669f622c0e978754083aad3d7916594828ad5c3b634cb8374b7a841e153/uv-0.10.5-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:0fbd426d2c215098cd8e08dfa36ad0a313ebe5eb90107ab7b3b8d5563b9b0c03", size = 22124089, upload-time = "2026-02-24T00:55:20.916Z" }, - { url = "https://files.pythonhosted.org/packages/1f/0a/e9f44902757ec1723e8f1970463ce477ce11c79fa52a09001fbc8934128a/uv-0.10.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:24825579973a05b7d482f1bba5e1b6d687d8e6ddf0ca088ff893e94ab34943a2", size = 22828770, upload-time = "2026-02-24T00:55:26.571Z" }, - { url = "https://files.pythonhosted.org/packages/37/18/d69ba9636c560b771b96c08bcfb4424829cc53983d8c7b71e0d2f301e7fb/uv-0.10.5-py3-none-musllinux_1_1_i686.whl", hash = "sha256:0338429ec4bb0b64620d05905a3fc1dc420df2a0e22b1a9b01dcc9e430067622", size = 22530138, upload-time = "2026-02-24T00:55:13.363Z" }, - { url = "https://files.pythonhosted.org/packages/92/72/15ef087c4a4ab1531d77b267345a2321301b09345fbe6419f8a8b94ffc3d/uv-0.10.5-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:515042b1f4a05396496a3db9ffc338b2f8f7bb39214fdbcb425b0462630f9270", size = 23448538, upload-time = "2026-02-24T00:54:53.364Z" }, - { url = "https://files.pythonhosted.org/packages/c4/5c/b07bc4fd89fad1a0b7946d40469850552738613fcd678a4ecee5e892aa8c/uv-0.10.5-py3-none-win32.whl", hash = "sha256:b235b4a5f25fb3bb93b96aebb6a2623eda0c2f48a6471b172a89e10444aa3626", size = 21507185, upload-time = "2026-02-24T00:55:01.646Z" }, - { url = "https://files.pythonhosted.org/packages/43/31/c564541cd1a27001a245241e1ac82ef4132fb5d96cab13a4a19e91981eaf/uv-0.10.5-py3-none-win_amd64.whl", hash = "sha256:4924af9facedde12eba2190463d84a4940062a875322e29ef59c8f447951e5c7", size = 23945906, upload-time = "2026-02-24T00:55:04.065Z" }, - { url = "https://files.pythonhosted.org/packages/e0/f5/71fa52581b25d5aa8917b3d3956db9c3d1ed511d4785bb7c94bf02872160/uv-0.10.5-py3-none-win_arm64.whl", hash = "sha256:43445370bb0729917b9a61d18bc3aec4e55c12e86463e6c4536fafde4d4da9e0", size = 22343346, upload-time = "2026-02-24T00:55:23.699Z" }, +version = "0.10.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/ec/b324a43b55fe59577505478a396cb1d2758487a2e2270c81ccfa4ac6c96d/uv-0.10.7.tar.gz", hash = "sha256:7c3b0133c2d6bd725d5a35ec5e109ebf0d75389943abe826f3d9ea6d6667a375", size = 3922193, upload-time = "2026-02-27T12:33:58.525Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/1b/decff24553325561850d70b75c737076e6fcbcfbf233011a27a33f06e4d9/uv-0.10.7-py3-none-linux_armv6l.whl", hash = "sha256:6a0af6c7a90fd2053edfa2c8ee719078ea906a2d9f4798d3fb3c03378726209a", size = 22497542, upload-time = "2026-02-27T12:33:39.425Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b5/51152c87921bc2576fecb982df4a02ac9cfd7fc934e28114a1232b99eed4/uv-0.10.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3b7db0cab77232a7c8856062904fc3b9db22383f1dec7e97a9588fb6c8470f6a", size = 21558860, upload-time = "2026-02-27T12:34:03.362Z" }, + { url = "https://files.pythonhosted.org/packages/5e/15/8365dc2ded350a4ee5fcbbf9b15195cb2b45855114f2a154b5effb6fa791/uv-0.10.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d872d2ff9c9dfba989b5f05f599715bc0f19b94cd0dbf8ae4ad22f8879a66c8c", size = 20212775, upload-time = "2026-02-27T12:33:55.365Z" }, + { url = "https://files.pythonhosted.org/packages/53/a0/ccf25e897f3907b5a6fd899007ff9a80b5bbf151b3a75a375881005611fd/uv-0.10.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:d9b40d03693efda80a41e5d18ac997efdf1094b27fb75471c1a8f51a9ebeffb3", size = 22015584, upload-time = "2026-02-27T12:33:47.374Z" }, + { url = "https://files.pythonhosted.org/packages/fa/3a/5099747954e7774768572d30917bb6bda6b8d465d7a3c49c9bbf7af2a812/uv-0.10.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:e74fe4df9cf31fe84f20b84a0054874635077d31ce20e7de35ff0dd64d498d7b", size = 22100376, upload-time = "2026-02-27T12:34:06.169Z" }, + { url = "https://files.pythonhosted.org/packages/0c/1a/75897fd966b871803cf78019fa31757ced0d54af5ffd7f57bce8b01d64f3/uv-0.10.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9c76659fc8bb618dd35cd83b2f479c6f880555a16630a454a251045c4c118ea4", size = 22105202, upload-time = "2026-02-27T12:34:16.972Z" }, + { url = "https://files.pythonhosted.org/packages/b5/1e/0b8caedd66ca911533e18fd051da79a213c792404138812c66043d529b9e/uv-0.10.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d160cceb9468024ca40dc57a180289dfd2024d98e42f2284b9ec44355723b0a", size = 23335601, upload-time = "2026-02-27T12:34:11.161Z" }, + { url = "https://files.pythonhosted.org/packages/69/94/b741af277e39a92e0da07fe48c338eee1429c2607e7a192e41345208bb24/uv-0.10.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c775975d891cb60cf10f00953e61e643fcb9a9139e94c9ef5c805fe36e90477f", size = 24152851, upload-time = "2026-02-27T12:33:33.904Z" }, + { url = "https://files.pythonhosted.org/packages/27/b2/da351ccd02f0fb1aec5f992b886bea1374cce44276a78904348e2669dd78/uv-0.10.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a709e75583231cc1f39567fb3d8d9b4077ff94a64046eb242726300144ed1a4a", size = 23276444, upload-time = "2026-02-27T12:33:36.891Z" }, + { url = "https://files.pythonhosted.org/packages/71/a9/2735cc9dc39457c9cf64d1ce2ba5a9a8ecbb103d0fb64b052bf33ba3d669/uv-0.10.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89de2504407dcf04aece914c6ca3b9d8e60cf9ff39a13031c1df1f7c040cea81", size = 23218464, upload-time = "2026-02-27T12:34:00.904Z" }, + { url = "https://files.pythonhosted.org/packages/20/5f/5f204e9c3f04f5fc844d2f98d80a7de64b6b304af869644ab478d909f6ff/uv-0.10.7-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:9945de1d11c4a5ad77e9c4f36f8b5f9e7c9c3c32999b8bc0e7e579145c3b641c", size = 22092562, upload-time = "2026-02-27T12:34:14.155Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a4/16bebf106e3289a29cc1e1482d551c49bd220983e9b4bc5960142389ad3f/uv-0.10.7-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:dbe43527f478e2ffa420516aa465f82057763936bbea56f814fd054a9b7f961f", size = 22851312, upload-time = "2026-02-27T12:34:08.651Z" }, + { url = "https://files.pythonhosted.org/packages/d1/7a/953b1da589225d98ca8668412f665c3192f6deed2a0f4bb782b0df18f611/uv-0.10.7-py3-none-musllinux_1_1_i686.whl", hash = "sha256:c0783f327631141501bdc5f31dd2b4c748df7e7f5dc5cdbfc0fbb82da86cc9ca", size = 22543775, upload-time = "2026-02-27T12:33:30.935Z" }, + { url = "https://files.pythonhosted.org/packages/8b/67/e133afdabf76e43989448be1c2ef607f13afc32aa1ee9f6897115dec8417/uv-0.10.7-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:eba438899010522812d3497af586e6eedc94fa2b0ced028f51812f0c10aafb30", size = 23431187, upload-time = "2026-02-27T12:33:42.131Z" }, + { url = "https://files.pythonhosted.org/packages/ba/40/6ffb58ec88a33d6cbe9a606966f9558807f37a50f7be7dc756824df2d04c/uv-0.10.7-py3-none-win32.whl", hash = "sha256:b56d1818aafb2701d92e94f552126fe71d30a13f28712d99345ef5cafc53d874", size = 21524397, upload-time = "2026-02-27T12:33:44.579Z" }, + { url = "https://files.pythonhosted.org/packages/e3/1f/74f4d625db838f716a555908d41777b6357bacc141ddef117a01855e5ef9/uv-0.10.7-py3-none-win_amd64.whl", hash = "sha256:ad0d0ddd9f5407ad8699e3b20fe6c18406cd606336743e246b16914801cfd8b0", size = 23999929, upload-time = "2026-02-27T12:33:49.839Z" }, + { url = "https://files.pythonhosted.org/packages/48/4e/20cbfbcb1a0f48c5c1ca94f6baa0fa00754aafda365da9160c15e3b9c277/uv-0.10.7-py3-none-win_arm64.whl", hash = "sha256:edf732de80c1a9701180ef8c7a2fa926a995712e4a34ae8c025e090f797c2e0b", size = 22353084, upload-time = "2026-02-27T12:33:52.792Z" }, ] [[package]] From 4322653b9a013272f90a2024c90464ad5e0dbf55 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Fri, 27 Feb 2026 23:51:03 +0000 Subject: [PATCH 09/14] Fix trailing whitespace in foundry_single_agent agent.yaml Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml index 69c6ea94a9..ef8901d2e0 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml @@ -4,7 +4,7 @@ name: foundry-single-agent displayName: "Foundry Single Agent with Local Tools" description: > A travel assistant agent that helps users find hotels in Seattle. - Demonstrates local Python tool execution - a key advantage of code-based + Demonstrates local Python tool execution - a key advantage of code-based hosted agents over prompt agents. metadata: authors: From 706b3fb43c9ec186ffab6d921513211ad06925df Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Tue, 3 Mar 2026 15:25:48 +0000 Subject: [PATCH 10/14] Exclude dotnet.microsoft.com from link checker This domain intermittently times out in CI, causing flaky markdown link check failures unrelated to PR changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/.linkspector.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/.linkspector.yml b/.github/.linkspector.yml index eb365c2982..c0e4c69191 100644 --- a/.github/.linkspector.yml +++ b/.github/.linkspector.yml @@ -20,6 +20,7 @@ ignorePatterns: - pattern: "https://your-resource.openai.azure.com/" - pattern: "http://host.docker.internal" - pattern: "https://openai.github.io/openai-agents-js/openai/agents/classes/" + - pattern: "https:\/\/dotnet.microsoft.com" # excludedDirs: # Folders which include links to localhost, since it's not ignored with regular expressions baseUrl: https://github.com/microsoft/agent-framework/ From 23a71b2f2a511a6c501f8d669732966812c07517 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Tue, 3 Mar 2026 15:32:47 +0000 Subject: [PATCH 11/14] Align env vars to AZURE_AI_PROJECT_ENDPOINT and default model to gpt-4o-mini Addresses PR review feedback: - Rename PROJECT_ENDPOINT to AZURE_AI_PROJECT_ENDPOINT across all Foundry samples (dotnet + python) to match existing samples - Change default model from gpt-4.1-mini to gpt-4o-mini consistently Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../HostedAgents/FoundryMultiAgent/Program.cs | 4 ++-- .../HostedAgents/FoundryMultiAgent/README.md | 8 ++++---- .../HostedAgents/FoundryMultiAgent/agent.yaml | 4 ++-- .../FoundryMultiAgent/appsettings.Development.json | 4 ++-- .../HostedAgents/FoundrySingleAgent/Program.cs | 2 +- .../HostedAgents/FoundrySingleAgent/README.md | 6 +++--- .../hosted_agents/foundry_multiagent/README.md | 12 ++++++------ .../hosted_agents/foundry_multiagent/agent.yaml | 4 ++-- .../hosted_agents/foundry_multiagent/main.py | 6 +++--- .../hosted_agents/foundry_single_agent/README.md | 12 ++++++------ .../hosted_agents/foundry_single_agent/agent.yaml | 4 ++-- .../hosted_agents/foundry_single_agent/main.py | 4 ++-- 12 files changed, 35 insertions(+), 35 deletions(-) diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs index 7c393ff125..138efb0096 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/Program.cs @@ -9,8 +9,8 @@ using Microsoft.Agents.AI; using Microsoft.Agents.AI.Workflows; -var endpoint = Environment.GetEnvironmentVariable("PROJECT_ENDPOINT") - ?? throw new InvalidOperationException("PROJECT_ENDPOINT is not set."); +var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") + ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set."); var deploymentName = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; Console.WriteLine($"Using Azure AI endpoint: {endpoint}"); diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md index 6b71326e9d..314320880b 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md @@ -65,15 +65,15 @@ Set the following environment variables: ```powershell # Replace with your actual values -$env:PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" -$env:MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +$env:AZURE_AI_PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" +$env:MODEL_DEPLOYMENT_NAME="gpt-4o-mini" ``` **Bash:** ```bash -export PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" -export MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +export AZURE_AI_PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" +export MODEL_DEPLOYMENT_NAME="gpt-4o-mini" ``` ### Running the Sample diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/agent.yaml b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/agent.yaml index 8f3abe5f53..70b82abf7c 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/agent.yaml +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/agent.yaml @@ -21,8 +21,8 @@ template: - protocol: responses version: v1 environment_variables: - - name: PROJECT_ENDPOINT - value: ${PROJECT_ENDPOINT} + - name: AZURE_AI_PROJECT_ENDPOINT + value: ${AZURE_AI_PROJECT_ENDPOINT} - name: MODEL_DEPLOYMENT_NAME value: gpt-4o-mini resources: diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/appsettings.Development.json b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/appsettings.Development.json index c5e5ebd833..b6b1c77b85 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/appsettings.Development.json +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/appsettings.Development.json @@ -1,4 +1,4 @@ { - "PROJECT_ENDPOINT": "https://.services.ai.azure.com/api/projects/", - "MODEL_DEPLOYMENT_NAME": "gpt-4.1-mini" + "AZURE_AI_PROJECT_ENDPOINT": "https://.services.ai.azure.com/api/projects/", + "MODEL_DEPLOYMENT_NAME": "gpt-4o-mini" } diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs index d8e323bf8f..759636bcc0 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/Program.cs @@ -17,7 +17,7 @@ // Get configuration from environment variables var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set."); -var deploymentName = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME") ?? "gpt-4.1-mini"; +var deploymentName = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; Console.WriteLine($"Project Endpoint: {endpoint}"); Console.WriteLine($"Model Deployment: {deploymentName}"); // Simulated hotel data for Seattle diff --git a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/README.md b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/README.md index 04dbca86d0..31f3fc1a9d 100644 --- a/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/README.md +++ b/dotnet/samples/05-end-to-end/HostedAgents/FoundrySingleAgent/README.md @@ -58,21 +58,21 @@ Before running this sample, ensure you have: Set the following environment variables (matching `agent.yaml`): - `AZURE_AI_PROJECT_ENDPOINT` - Your Azure AI Foundry project endpoint URL (required) -- `MODEL_DEPLOYMENT_NAME` - The deployment name for your chat model (defaults to `gpt-4.1-mini`) +- `MODEL_DEPLOYMENT_NAME` - The deployment name for your chat model (defaults to `gpt-4o-mini`) **PowerShell:** ```powershell # Replace with your actual values $env:AZURE_AI_PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" -$env:MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +$env:MODEL_DEPLOYMENT_NAME="gpt-4o-mini" ``` **Bash:** ```bash export AZURE_AI_PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" -export MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +export MODEL_DEPLOYMENT_NAME="gpt-4o-mini" ``` ### Running the Sample diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md index 5abdbce392..4e203fc89f 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md +++ b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md @@ -62,24 +62,24 @@ Before running this sample, ensure you have: Set the following environment variables: -- `PROJECT_ENDPOINT` - Your Microsoft Foundry project endpoint URL (required) -- `MODEL_DEPLOYMENT_NAME` - The deployment name for your chat model (defaults to `gpt-4.1-mini`) +- `AZURE_AI_PROJECT_ENDPOINT` - Your Microsoft Foundry project endpoint URL (required) +- `MODEL_DEPLOYMENT_NAME` - The deployment name for your chat model (defaults to `gpt-4o-mini`) This sample loads environment variables from a local `.env` file if present. Create a `.env` file in this directory with the following content: ``` -PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ -MODEL_DEPLOYMENT_NAME=gpt-4.1-mini +AZURE_AI_PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ +MODEL_DEPLOYMENT_NAME=gpt-4o-mini ``` Or set them via PowerShell: ```powershell # Replace with your actual values -$env:PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" -$env:MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +$env:AZURE_AI_PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" +$env:MODEL_DEPLOYMENT_NAME="gpt-4o-mini" ``` ### Setting Up a Virtual Environment diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml index bb854430bc..4b0ca606fb 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml +++ b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml @@ -21,8 +21,8 @@ template: - protocol: responses version: v1 environment_variables: - - name: PROJECT_ENDPOINT - value: ${PROJECT_ENDPOINT} + - name: AZURE_AI_PROJECT_ENDPOINT + value: ${AZURE_AI_PROJECT_ENDPOINT} - name: MODEL_DEPLOYMENT_NAME value: gpt-4o-mini resources: diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py index fc8d20cc54..32fb6f965e 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py +++ b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py @@ -13,10 +13,10 @@ # Configure these for your Foundry project # Read the explicit variables present in the .env file PROJECT_ENDPOINT = os.getenv( - "PROJECT_ENDPOINT" + "AZURE_AI_PROJECT_ENDPOINT" ) # e.g., "https://.services.ai.azure.com" MODEL_DEPLOYMENT_NAME = os.getenv( - "MODEL_DEPLOYMENT_NAME", "gpt-4.1-mini" + "MODEL_DEPLOYMENT_NAME", "gpt-4o-mini" ) # Your model deployment name e.g., "gpt-4.1-mini" @@ -75,7 +75,7 @@ async def main() -> None: python main.py # Run in server mode Environment variables required: - - PROJECT_ENDPOINT: Your Microsoft Foundry project endpoint + - AZURE_AI_PROJECT_ENDPOINT: Your Microsoft Foundry project endpoint - MODEL_DEPLOYMENT_NAME: Your Microsoft Foundry model deployment name """ diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md index 9e89d286c2..e21935f52a 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md @@ -59,24 +59,24 @@ Before running this sample, ensure you have: Set the following environment variables: -- `PROJECT_ENDPOINT` - Your Microsoft Foundry project endpoint URL (required) -- `MODEL_DEPLOYMENT_NAME` - The deployment name for your chat model (defaults to `gpt-4.1-mini`) +- `AZURE_AI_PROJECT_ENDPOINT` - Your Microsoft Foundry project endpoint URL (required) +- `MODEL_DEPLOYMENT_NAME` - The deployment name for your chat model (defaults to `gpt-4o-mini`) This sample loads environment variables from a local `.env` file if present. Create a `.env` file in this directory with the following content: ``` -PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ -MODEL_DEPLOYMENT_NAME=gpt-4.1-mini +AZURE_AI_PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ +MODEL_DEPLOYMENT_NAME=gpt-4o-mini ``` Or set them via PowerShell: ```powershell # Replace with your actual values -$env:PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" -$env:MODEL_DEPLOYMENT_NAME="gpt-4.1-mini" +$env:AZURE_AI_PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" +$env:MODEL_DEPLOYMENT_NAME="gpt-4o-mini" ``` ### Setting Up a Virtual Environment diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml index ef8901d2e0..3811c3c561 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml @@ -22,8 +22,8 @@ template: - protocol: responses version: v1 environment_variables: - - name: PROJECT_ENDPOINT - value: ${PROJECT_ENDPOINT} + - name: AZURE_AI_PROJECT_ENDPOINT + value: ${AZURE_AI_PROJECT_ENDPOINT} - name: MODEL_DEPLOYMENT_NAME value: gpt-4o-mini resources: diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py index 38fba192e4..57aa9ed445 100644 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py +++ b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py @@ -19,10 +19,10 @@ # Configure these for your Foundry project # Read the explicit variables present in the .env file PROJECT_ENDPOINT = os.getenv( - "PROJECT_ENDPOINT" + "AZURE_AI_PROJECT_ENDPOINT" ) # e.g., "https://.services.ai.azure.com" MODEL_DEPLOYMENT_NAME = os.getenv( - "MODEL_DEPLOYMENT_NAME", "gpt-4.1-mini" + "MODEL_DEPLOYMENT_NAME", "gpt-4o-mini" ) # Your model deployment name e.g., "gpt-4.1-mini" From 4291e2e520c2c345c018cd0fab640cdefe8f4108 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:11:55 +0000 Subject: [PATCH 12/14] Skip flaky test CreatesWorkflowEndToEndActivities_WithCorrectName_DefaultAsync Tracked in #4398 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../ObservabilityTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/ObservabilityTests.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/ObservabilityTests.cs index be45f55104..34c7e88a0b 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/ObservabilityTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/ObservabilityTests.cs @@ -133,7 +133,7 @@ private async Task TestWorkflowEndToEndActivitiesAsync(string executionEnvironme activityEvents.Should().Contain(e => e.Name == EventNames.WorkflowCompleted, "activity should have workflow completed event"); } - [Fact] + [Fact(Skip = "Flaky test - temporarily disabled")] public async Task CreatesWorkflowEndToEndActivities_WithCorrectName_DefaultAsync() { await this.TestWorkflowEndToEndActivitiesAsync("Default"); From 0ab0d6d40509d6483d5947dae2375db2ce2df1c1 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:52:07 +0000 Subject: [PATCH 13/14] Remove Python foundry samples from PR scope Python hosted agent samples need further alignment with the azure-ai package conventions. Removing from this PR to ship .NET samples first. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../05-end-to-end/hosted_agents/README.md | 21 -- .../foundry_multiagent/Dockerfile | 15 -- .../foundry_multiagent/README.md | 188 ------------------ .../foundry_multiagent/agent.yaml | 31 --- .../hosted_agents/foundry_multiagent/main.py | 107 ---------- .../foundry_multiagent/requirements.txt | 2 - .../foundry_single_agent/Dockerfile | 15 -- .../foundry_single_agent/README.md | 179 ----------------- .../foundry_single_agent/agent.yaml | 32 --- .../foundry_single_agent/main.py | 148 -------------- .../foundry_single_agent/requirements.txt | 2 - 11 files changed, 740 deletions(-) delete mode 100644 python/samples/05-end-to-end/hosted_agents/README.md delete mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_multiagent/Dockerfile delete mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md delete mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml delete mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py delete mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt delete mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_single_agent/Dockerfile delete mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md delete mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml delete mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py delete mode 100644 python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt diff --git a/python/samples/05-end-to-end/hosted_agents/README.md b/python/samples/05-end-to-end/hosted_agents/README.md deleted file mode 100644 index 88ef861d2e..0000000000 --- a/python/samples/05-end-to-end/hosted_agents/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Hosted Agent Samples - -These samples demonstrate how to build and deploy **code-based hosted agents** using the [Azure AI AgentServer SDK](https://pypi.org/project/azure-ai-agentserver-agentframework/). Each sample can run locally and be deployed to Microsoft Foundry. - -## Samples - -| Sample | Description | -|--------|-------------| -| [`agents_in_workflow`](./agents_in_workflow/) | Translation workflow with 3 sequential agents (French → Spanish → English) | -| [`agent_with_hosted_mcp`](./agent_with_hosted_mcp/) | Agent with Hosted MCP server integration for Microsoft Learn documentation search | -| [`agent_with_text_search_rag`](./agent_with_text_search_rag/) | RAG pattern with text search for pre-invocation document retrieval | -| [`foundry_multiagent`](./foundry_multiagent/) | Multi-agent Writer-Reviewer workflow using Azure AI Foundry agents | -| [`foundry_single_agent`](./foundry_single_agent/) | Single agent with local tool execution (hotel search) using Azure AI Foundry | - -## Prerequisites - -- Python 3.10 or later -- Azure AI Foundry Project with a deployed chat model -- Azure CLI (`az login`) - -See each sample's README for specific setup instructions. diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/Dockerfile b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/Dockerfile deleted file mode 100644 index 413c6acb62..0000000000 --- a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM python:3.12-slim - -WORKDIR /app - -COPY ./ . - -RUN if [ -f requirements.txt ]; then \ - pip install --no-cache-dir -r requirements.txt; \ - else \ - echo "No requirements.txt found"; \ - fi - -EXPOSE 8088 - -CMD ["python", "main.py"] diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md deleted file mode 100644 index 4e203fc89f..0000000000 --- a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/README.md +++ /dev/null @@ -1,188 +0,0 @@ -**IMPORTANT!** All samples and other resources made available in this GitHub repository ("samples") are designed to assist in accelerating development of agents, solutions, and agent workflows for various scenarios. Review all provided resources and carefully test output behavior in the context of your use case. AI responses may be inaccurate and AI actions should be monitored with human oversight. Learn more in the transparency documents for [Agent Service](https://learn.microsoft.com/en-us/azure/ai-foundry/responsible-ai/agents/transparency-note) and [Agent Framework](https://github.com/microsoft/agent-framework/blob/main/TRANSPARENCY_FAQ.md). - -Agents, solutions, or other output you create may be subject to legal and regulatory requirements, may require licenses, or may not be suitable for all industries, scenarios, or use cases. By using any sample, you are acknowledging that any output created using those samples are solely your responsibility, and that you will comply with all applicable laws, regulations, and relevant safety standards, terms of service, and codes of conduct. - -Third-party samples contained in this folder are subject to their own designated terms, and they have not been tested or verified by Microsoft or its affiliates. - -Microsoft has no responsibility to you or others with respect to any of these samples or any resulting output. - -# What this sample demonstrates - -This sample demonstrates a **key advantage of code-based hosted agents**: - -- **Multi-agent workflows** - Orchestrate multiple agents working together - -Code-based agents can execute **any Python code** you write. This sample includes a **Writer-Reviewer workflow** where two agents collaborate: a Writer creates content and a Reviewer provides feedback. - -The agent is hosted using the [Azure AI AgentServer SDK](https://pypi.org/project/azure-ai-agentserver-agentframework/) and can be deployed to Microsoft Foundry. - -## How It Works - -### Multi-Agent Workflow - -In [main.py](main.py), the sample creates two agents: - -- **Writer** - An agent that creates and edits content based on feedback -- **Reviewer** - An agent that provides actionable feedback on the content - -The `WorkflowBuilder` connects these agents in a sequential flow: - -1. The Writer receives the initial request and generates content -2. The Reviewer evaluates the content and provides feedback -3. Both agent responses are output to the user. - -### Agent Hosting - -The agent is hosted using the [Azure AI AgentServer SDK](https://pypi.org/project/azure-ai-agentserver-agentframework/), -which provisions a REST API endpoint compatible with the OpenAI Responses protocol. - -## Running the Agent Locally - -### Prerequisites - -Before running this sample, ensure you have: - -1. **Microsoft Foundry Project** - - A Microsoft Project created. - - Chat model deployed (e.g., `gpt-4o` or `gpt-4.1`). - - Note your project endpoint URL and model deployment name. - -2. **Azure CLI** - - Installed and authenticated - - Run `az login` and verify with `az account show` - -3. **Python 3.10 or higher** - - Verify your version: `python --version` - - If you have Python 3.9 or older, install a newer version: - - Windows: `winget install Python.Python.3.12` - - macOS: `brew install python@3.12` - - Linux: Use your package manager - -### Environment Variables - -Set the following environment variables: - -- `AZURE_AI_PROJECT_ENDPOINT` - Your Microsoft Foundry project endpoint URL (required) -- `MODEL_DEPLOYMENT_NAME` - The deployment name for your chat model (defaults to `gpt-4o-mini`) - -This sample loads environment variables from a local `.env` file if present. - -Create a `.env` file in this directory with the following content: - -``` -AZURE_AI_PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ -MODEL_DEPLOYMENT_NAME=gpt-4o-mini -``` - -Or set them via PowerShell: - -```powershell -# Replace with your actual values -$env:AZURE_AI_PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" -$env:MODEL_DEPLOYMENT_NAME="gpt-4o-mini" -``` - -### Setting Up a Virtual Environment - -It's recommended to use a virtual environment to isolate project dependencies: - -**macOS/Linux:** - -```bash -python -m venv .venv -source .venv/bin/activate -``` - -**Windows (PowerShell):** - -```powershell -python -m venv .venv -.\.venv\Scripts\Activate.ps1 -``` - -### Installing Dependencies - -Install the required Python dependencies using pip: - -```bash -pip install -r requirements.txt -``` - -The required packages are: - -- `azure-ai-agentserver-agentframework` - Agent Framework and AgentServer SDK - -### Running the Sample - -Run as HTTP server (default): - -```bash -python main.py -``` - -This will start the hosted agent locally on `http://localhost:8088/`. - -**PowerShell (Windows):** - -```powershell -$body = @{ - input = "Create a slogan for a new electric SUV that is affordable and fun to drive" - stream = $false -} | ConvertTo-Json - -Invoke-RestMethod -Uri http://localhost:8088/responses -Method Post -Body $body -ContentType "application/json" -``` - -**Bash/curl (Linux/macOS):** - -```bash -curl -sS -H "Content-Type: application/json" -X POST http://localhost:8088/responses \ - -d '{"input": "Create a slogan for a new electric SUV that is affordable and fun to drive","stream":false}' -``` - -The agent will respond with both the Writer's slogan and the Reviewer's feedback. - -Or run in CLI mode for quick testing: - -```bash -python main.py --cli -``` - -## Deploying the Agent to Microsoft Foundry - -To deploy the hosted agent: - -1. Open the VS Code Command Palette and run the `Microsoft Foundry: Deploy Hosted Agent` command. - -2. Follow the interactive deployment prompts. The extension will help you select or create the container files it needs: - - It first looks for a Dockerfile at the repository root. If not found, you can select an existing Dockerfile or generate a new one. - - If you choose to generate a Dockerfile, the extension will place the files at the repo root and open the Dockerfile in the editor; the deployment flow is intentionally cancelled in that case so you can review and edit the generated files before re-running the deploy command. - -3. After deployment completes, the hosted agent appears under the `Hosted Agents (Preview)` section of the extension tree. You can select the agent there to view details and test it using the integrated playground. - -**What the deploy flow does for you:** - -- Creates or obtains an Azure Container Registry for the target project. -- Builds and pushes a container image from your workspace (the build packages the workspace respecting `.dockerignore`). -- Creates an agent version in Microsoft Foundry using the built image. If a `.env` file exists at the workspace root, the extension will parse it and include its key/value pairs as the hosted agent's environment variables in the create request (these variables will be available to the agent runtime). -- Starts the agent container on the project's capability host. If the capability host is not provisioned, the extension will prompt you to enable it and will guide you through creating it. - -### MSI Configuration in the Azure Portal - -This sample requires the Microsoft Foundry Project to authenticate using a Managed Identity when running remotely in Azure. Grant the project's managed identity the required permissions by assigning the built-in [Azure AI User](https://aka.ms/foundry-ext-project-role) role. - -To configure the Managed Identity: - -1. In the Azure Portal, open the Foundry Project. -2. Select "Access control (IAM)" from the left-hand menu. -3. Click "Add" and choose "Add role assignment". -4. In the role selection, search for and select "Azure AI User", then click "Next". -5. For "Assign access to", choose "Managed identity". -6. Click "Select members", locate the managed identity associated with your Foundry Project (you can search by the project name), then click "Select". -7. Click "Review + assign" to complete the assignment. -8. Allow a few minutes for the role assignment to propagate before running the application. - -## Additional Resources - -- [Microsoft Agents Framework](https://learn.microsoft.com/en-us/agent-framework/overview/agent-framework-overview) -- [Managed Identities for Azure Resources](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/) diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml deleted file mode 100644 index 4b0ca606fb..0000000000 --- a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/agent.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml - -name: foundry-multiagent -displayName: "Foundry Multi-Agent Workflow" -description: > - A multi-agent workflow featuring a Writer and Reviewer that collaborate - to create and refine content using Azure AI Foundry. -metadata: - authors: - - Microsoft Agent Framework Team - tags: - - Azure AI AgentServer - - Microsoft Agent Framework - - Multi-Agent Workflow - - Writer-Reviewer - - Content Creation -template: - kind: hosted - name: foundry-multiagent - protocols: - - protocol: responses - version: v1 - environment_variables: - - name: AZURE_AI_PROJECT_ENDPOINT - value: ${AZURE_AI_PROJECT_ENDPOINT} - - name: MODEL_DEPLOYMENT_NAME - value: gpt-4o-mini -resources: - - name: "gpt-4o-mini" - kind: model - id: gpt-4o-mini diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py deleted file mode 100644 index 32fb6f965e..0000000000 --- a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/main.py +++ /dev/null @@ -1,107 +0,0 @@ -import asyncio -import os -import sys -from contextlib import asynccontextmanager - -from agent_framework import WorkflowBuilder -from agent_framework.azure import AzureAIAgentClient -from azure.identity.aio import DefaultAzureCredential, ManagedIdentityCredential -from dotenv import load_dotenv - -load_dotenv(override=True) - -# Configure these for your Foundry project -# Read the explicit variables present in the .env file -PROJECT_ENDPOINT = os.getenv( - "AZURE_AI_PROJECT_ENDPOINT" -) # e.g., "https://.services.ai.azure.com" -MODEL_DEPLOYMENT_NAME = os.getenv( - "MODEL_DEPLOYMENT_NAME", "gpt-4o-mini" -) # Your model deployment name e.g., "gpt-4.1-mini" - - -def get_credential(): - """Will use Managed Identity when running in Azure, otherwise falls back to DefaultAzureCredential.""" - return ( - ManagedIdentityCredential() - if os.getenv("MSI_ENDPOINT") - else DefaultAzureCredential() - ) - - -@asynccontextmanager -async def create_agents(): - async with ( - get_credential() as credential, - AzureAIAgentClient( - project_endpoint=PROJECT_ENDPOINT, - model_deployment_name=MODEL_DEPLOYMENT_NAME, - credential=credential, - ) as writer_client, - AzureAIAgentClient( - project_endpoint=PROJECT_ENDPOINT, - model_deployment_name=MODEL_DEPLOYMENT_NAME, - credential=credential, - ) as reviewer_client, - ): - writer = writer_client.create_agent( - name="Writer", - instructions="You are an excellent content writer. You create new content and edit contents based on the feedback.", - ) - reviewer = reviewer_client.create_agent( - name="Reviewer", - instructions="You are an excellent content reviewer. Provide actionable feedback to the writer about the provided content in the most concise manner possible.", - ) - yield writer, reviewer - - -def create_workflow(writer, reviewer): - workflow = ( - WorkflowBuilder(name="Writer-Reviewer") - .register_agent(lambda: writer, name="Writer", output_response=True) - .register_agent(lambda: reviewer, name="Reviewer", output_response=True) - .set_start_executor("Writer") - .add_edge("Writer", "Reviewer") - .build() - ) - return workflow.as_agent() - - -async def main() -> None: - """ - The writer and reviewer multi-agent workflow. - - Usage: - python main.py # Run in server mode - - Environment variables required: - - AZURE_AI_PROJECT_ENDPOINT: Your Microsoft Foundry project endpoint - - MODEL_DEPLOYMENT_NAME: Your Microsoft Foundry model deployment name - """ - - async with create_agents() as (writer, reviewer): - agent = create_workflow(writer, reviewer) - - # Check if running in CLI mode (default is server mode) - if "--cli" in sys.argv: - # CLI mode for testing - print("Running workflow agent in CLI mode...") - - # Test with a sample query - user_message = "Create a slogan for a new electric SUV that is affordable and fun to drive." - print(f"\nUser: {user_message}\n") - - response = await agent.run(user_message) - for msg in response.messages: - if msg.text: - print(f"{msg.author_name}: {msg.text}\n") - else: - # Server mode (default) - print("Starting workflow agent HTTP server...") - from azure.ai.agentserver.agentframework import from_agent_framework - - await from_agent_framework(agent).run_async() - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt b/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt deleted file mode 100644 index 3cc5eab643..0000000000 --- a/python/samples/05-end-to-end/hosted_agents/foundry_multiagent/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -azure-ai-agentserver-agentframework==1.0.0b14 -agent-framework \ No newline at end of file diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/Dockerfile b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/Dockerfile deleted file mode 100644 index 413c6acb62..0000000000 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM python:3.12-slim - -WORKDIR /app - -COPY ./ . - -RUN if [ -f requirements.txt ]; then \ - pip install --no-cache-dir -r requirements.txt; \ - else \ - echo "No requirements.txt found"; \ - fi - -EXPOSE 8088 - -CMD ["python", "main.py"] diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md deleted file mode 100644 index e21935f52a..0000000000 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/README.md +++ /dev/null @@ -1,179 +0,0 @@ -**IMPORTANT!** All samples and other resources made available in this GitHub repository ("samples") are designed to assist in accelerating development of agents, solutions, and agent workflows for various scenarios. Review all provided resources and carefully test output behavior in the context of your use case. AI responses may be inaccurate and AI actions should be monitored with human oversight. Learn more in the transparency documents for [Agent Service](https://learn.microsoft.com/en-us/azure/ai-foundry/responsible-ai/agents/transparency-note) and [Agent Framework](https://github.com/microsoft/agent-framework/blob/main/TRANSPARENCY_FAQ.md). - -Agents, solutions, or other output you create may be subject to legal and regulatory requirements, may require licenses, or may not be suitable for all industries, scenarios, or use cases. By using any sample, you are acknowledging that any output created using those samples are solely your responsibility, and that you will comply with all applicable laws, regulations, and relevant safety standards, terms of service, and codes of conduct. - -Third-party samples contained in this folder are subject to their own designated terms, and they have not been tested or verified by Microsoft or its affiliates. - -Microsoft has no responsibility to you or others with respect to any of these samples or any resulting output. - -# What this sample demonstrates - -This sample demonstrates a **key advantage of code-based hosted agents**: - -- **Local Python tool execution** - Run custom Python functions as agent tools - -Code-based agents can execute **any Python code** you write. This sample includes a Seattle Hotel Agent with a `get_available_hotels` tool that searches for available hotels based on check-in/check-out dates and budget preferences. - -The agent is hosted using the [Azure AI AgentServer SDK](https://pypi.org/project/azure-ai-agentserver-agentframework/) and can be deployed to Microsoft Foundry. - -## How It Works - -### Local Tools Integration - -In [main.py](main.py), the agent uses a local Python function (`get_available_hotels`) that simulates a hotel availability API. This demonstrates how code-based agents can execute custom server-side logic that prompt agents cannot access. - -The tool accepts: - -- **check_in_date** - Check-in date in YYYY-MM-DD format -- **check_out_date** - Check-out date in YYYY-MM-DD format -- **max_price** - Maximum price per night in USD (optional, defaults to $500) - -### Agent Hosting - -The agent is hosted using the [Azure AI AgentServer SDK](https://pypi.org/project/azure-ai-agentserver-agentframework/), -which provisions a REST API endpoint compatible with the OpenAI Responses protocol. - -## Running the Agent Locally - -### Prerequisites - -Before running this sample, ensure you have: - -1. **Microsoft Foundry Project** - - A Microsoft Project created. - - Chat model deployed (e.g., `gpt-4o` or `gpt-4.1`). - - Note your project endpoint URL and model deployment name. - -2. **Azure CLI** - - Installed and authenticated - - Run `az login` and verify with `az account show` - -3. **Python 3.10 or higher** - - Verify your version: `python --version` - - If you have Python 3.9 or older, install a newer version: - - Windows: `winget install Python.Python.3.12` - - macOS: `brew install python@3.12` - - Linux: Use your package manager - -### Environment Variables - -Set the following environment variables: - -- `AZURE_AI_PROJECT_ENDPOINT` - Your Microsoft Foundry project endpoint URL (required) -- `MODEL_DEPLOYMENT_NAME` - The deployment name for your chat model (defaults to `gpt-4o-mini`) - -This sample loads environment variables from a local `.env` file if present. - -Create a `.env` file in this directory with the following content: - -``` -AZURE_AI_PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ -MODEL_DEPLOYMENT_NAME=gpt-4o-mini -``` - -Or set them via PowerShell: - -```powershell -# Replace with your actual values -$env:AZURE_AI_PROJECT_ENDPOINT="https://.services.ai.azure.com/api/projects/" -$env:MODEL_DEPLOYMENT_NAME="gpt-4o-mini" -``` - -### Setting Up a Virtual Environment - -It's recommended to use a virtual environment to isolate project dependencies: - -**macOS/Linux:** - -```bash -python -m venv .venv -source .venv/bin/activate -``` - -**Windows (PowerShell):** - -```powershell -python -m venv .venv -.\.venv\Scripts\Activate.ps1 -``` - -### Installing Dependencies - -Install the required Python dependencies using pip: - -```bash -pip install -r requirements.txt -``` - -The required packages are: - -- `azure-ai-agentserver-agentframework` - Agent Framework and AgentServer SDK - -### Running the Sample - -Run as HTTP server (default): - -```bash -python main.py -``` - -This will start the hosted agent locally on `http://localhost:8088/`. - -**PowerShell (Windows):** - -```powershell -$body = @{ - input = "I need a hotel in Seattle from 2025-03-15 to 2025-03-18, budget under `$200 per night" - stream = $false -} | ConvertTo-Json - -Invoke-RestMethod -Uri http://localhost:8088/responses -Method Post -Body $body -ContentType "application/json" -``` - -**Bash/curl (Linux/macOS):** - -```bash -curl -sS -H "Content-Type: application/json" -X POST http://localhost:8088/responses \ - -d '{"input": "Find me hotels in Seattle for March 20-23, 2025 under $200 per night","stream":false}' -``` - -The agent will use the `get_available_hotels` tool to search for available hotels matching your criteria. - -## Deploying the Agent to Microsoft Foundry - -To deploy the hosted agent: - -1. Open the VS Code Command Palette and run the `Microsoft Foundry: Deploy Hosted Agent` command. - -2. Follow the interactive deployment prompts. The extension will help you select or create the container files it needs: - - It first looks for a Dockerfile at the repository root. If not found, you can select an existing Dockerfile or generate a new one. - - If you choose to generate a Dockerfile, the extension will place the files at the repo root and open the Dockerfile in the editor; the deployment flow is intentionally cancelled in that case so you can review and edit the generated files before re-running the deploy command. - -3. After deployment completes, the hosted agent appears under the `Hosted Agents (Preview)` section of the extension tree. You can select the agent there to view details and test it using the integrated playground. - -**What the deploy flow does for you:** - -- Creates or obtains an Azure Container Registry for the target project. -- Builds and pushes a container image from your workspace (the build packages the workspace respecting `.dockerignore`). -- Creates an agent version in Microsoft Foundry using the built image. If a `.env` file exists at the workspace root, the extension will parse it and include its key/value pairs as the hosted agent's environment variables in the create request (these variables will be available to the agent runtime). -- Starts the agent container on the project's capability host. If the capability host is not provisioned, the extension will prompt you to enable it and will guide you through creating it. - -### MSI Configuration in the Azure Portal - -This sample requires the Microsoft Foundry Project to authenticate using a Managed Identity when running remotely in Azure. Grant the project's managed identity the required permissions by assigning the built-in [Azure AI User](https://aka.ms/foundry-ext-project-role) role. - -To configure the Managed Identity: - -1. In the Azure Portal, open the Foundry Project. -2. Select "Access control (IAM)" from the left-hand menu. -3. Click "Add" and choose "Add role assignment". -4. In the role selection, search for and select "Azure AI User", then click "Next". -5. For "Assign access to", choose "Managed identity". -6. Click "Select members", locate the managed identity associated with your Foundry Project (you can search by the project name), then click "Select". -7. Click "Review + assign" to complete the assignment. -8. Allow a few minutes for the role assignment to propagate before running the application. - -## Additional Resources - -- [Microsoft Agents Framework](https://learn.microsoft.com/en-us/agent-framework/overview/agent-framework-overview) -- [Managed Identities for Azure Resources](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/) diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml deleted file mode 100644 index 3811c3c561..0000000000 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/agent.yaml +++ /dev/null @@ -1,32 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml - -name: foundry-single-agent -displayName: "Foundry Single Agent with Local Tools" -description: > - A travel assistant agent that helps users find hotels in Seattle. - Demonstrates local Python tool execution - a key advantage of code-based - hosted agents over prompt agents. -metadata: - authors: - - Microsoft Agent Framework Team - tags: - - Azure AI AgentServer - - Microsoft Agent Framework - - Local Tools - - Travel Assistant - - Hotel Search -template: - kind: hosted - name: foundry-single-agent - protocols: - - protocol: responses - version: v1 - environment_variables: - - name: AZURE_AI_PROJECT_ENDPOINT - value: ${AZURE_AI_PROJECT_ENDPOINT} - - name: MODEL_DEPLOYMENT_NAME - value: gpt-4o-mini -resources: - - name: "gpt-4o-mini" - kind: model - id: gpt-4o-mini \ No newline at end of file diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py deleted file mode 100644 index 57aa9ed445..0000000000 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/main.py +++ /dev/null @@ -1,148 +0,0 @@ -""" -Seattle Hotel Agent - A simple agent with a tool to find hotels in Seattle. -Uses Microsoft Agent Framework with Azure AI Foundry. -Ready for deployment to Foundry Hosted Agent service. -""" - -import asyncio -import os -from datetime import datetime -from typing import Annotated - -from agent_framework.azure import AzureAIAgentClient -from azure.ai.agentserver.agentframework import from_agent_framework -from azure.identity.aio import DefaultAzureCredential -from dotenv import load_dotenv - -load_dotenv(override=True) - -# Configure these for your Foundry project -# Read the explicit variables present in the .env file -PROJECT_ENDPOINT = os.getenv( - "AZURE_AI_PROJECT_ENDPOINT" -) # e.g., "https://.services.ai.azure.com" -MODEL_DEPLOYMENT_NAME = os.getenv( - "MODEL_DEPLOYMENT_NAME", "gpt-4o-mini" -) # Your model deployment name e.g., "gpt-4.1-mini" - - -# Simulated hotel data for Seattle -SEATTLE_HOTELS = [ - { - "name": "Contoso Suites", - "price_per_night": 189, - "rating": 4.5, - "location": "Downtown", - }, - { - "name": "Fabrikam Residences", - "price_per_night": 159, - "rating": 4.2, - "location": "Pike Place Market", - }, - { - "name": "Alpine Ski House", - "price_per_night": 249, - "rating": 4.7, - "location": "Seattle Center", - }, - { - "name": "Margie's Travel Lodge", - "price_per_night": 219, - "rating": 4.4, - "location": "Waterfront", - }, - { - "name": "Northwind Inn", - "price_per_night": 139, - "rating": 4.0, - "location": "Capitol Hill", - }, - { - "name": "Relecloud Hotel", - "price_per_night": 99, - "rating": 3.8, - "location": "University District", - }, -] - - -def get_available_hotels( - check_in_date: Annotated[str, "Check-in date in YYYY-MM-DD format"], - check_out_date: Annotated[str, "Check-out date in YYYY-MM-DD format"], - max_price: Annotated[int, "Maximum price per night in USD (optional)"] = 500, -) -> str: - """ - Get available hotels in Seattle for the specified dates. - This simulates a call to a fake hotel availability API. - """ - try: - # Parse dates - check_in = datetime.strptime(check_in_date, "%Y-%m-%d") - check_out = datetime.strptime(check_out_date, "%Y-%m-%d") - - # Validate dates - if check_out <= check_in: - return "Error: Check-out date must be after check-in date." - - nights = (check_out - check_in).days - - # Filter hotels by price - available_hotels = [ - hotel for hotel in SEATTLE_HOTELS if hotel["price_per_night"] <= max_price - ] - - if not available_hotels: - return ( - f"No hotels found in Seattle within your budget of ${max_price}/night." - ) - - # Build response - result = f"Available hotels in Seattle from {check_in_date} to {check_out_date} ({nights} nights):\n\n" - - for hotel in available_hotels: - total_cost = hotel["price_per_night"] * nights - result += f"**{hotel['name']}**\n" - result += f" Location: {hotel['location']}\n" - result += f" Rating: {hotel['rating']}/5\n" - result += f" ${hotel['price_per_night']}/night (Total: ${total_cost})\n\n" - - return result - - except ValueError as e: - return f"Error parsing dates. Please use YYYY-MM-DD format. Details: {str(e)}" - - -async def main(): - """Main function to run the agent as a web server.""" - async with ( - DefaultAzureCredential() as credential, - AzureAIAgentClient( - project_endpoint=PROJECT_ENDPOINT, - model_deployment_name=MODEL_DEPLOYMENT_NAME, - credential=credential, - ) as client, - ): - agent = client.create_agent( - name="SeattleHotelAgent", - instructions="""You are a helpful travel assistant specializing in finding hotels in Seattle, Washington. - -When a user asks about hotels in Seattle: -1. Ask for their check-in and check-out dates if not provided -2. Ask about their budget preferences if not mentioned -3. Use the get_available_hotels tool to find available options -4. Present the results in a friendly, informative way -5. Offer to help with additional questions about the hotels or Seattle - -Be conversational and helpful. If users ask about things outside of Seattle hotels, -politely let them know you specialize in Seattle hotel recommendations.""", - tools=[get_available_hotels], - ) - - print("Seattle Hotel Agent Server running on http://localhost:8088") - server = from_agent_framework(agent) - await server.run_async() - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt b/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt deleted file mode 100644 index 3cc5eab643..0000000000 --- a/python/samples/05-end-to-end/hosted_agents/foundry_single_agent/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -azure-ai-agentserver-agentframework==1.0.0b14 -agent-framework \ No newline at end of file From 898f0ef925d3d750b7cbab22fbfa67ca42f0dde8 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:33:21 +0000 Subject: [PATCH 14/14] Narrow linkspector exclusion to dotnet.microsoft.com/download only Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/.linkspector.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/.linkspector.yml b/.github/.linkspector.yml index c0e4c69191..c0da7d36b2 100644 --- a/.github/.linkspector.yml +++ b/.github/.linkspector.yml @@ -20,7 +20,7 @@ ignorePatterns: - pattern: "https://your-resource.openai.azure.com/" - pattern: "http://host.docker.internal" - pattern: "https://openai.github.io/openai-agents-js/openai/agents/classes/" - - pattern: "https:\/\/dotnet.microsoft.com" + - pattern: "https:\/\/dotnet.microsoft.com\/download" # excludedDirs: # Folders which include links to localhost, since it's not ignored with regular expressions baseUrl: https://github.com/microsoft/agent-framework/