├── website ├── chatui.zip └── chatui │ ├── wwwroot │ └── favicon.ico │ ├── Controllers │ ├── HomeController.cs │ └── ChatController.cs │ ├── Configuration │ └── ChatApiOptions.cs │ ├── Properties │ └── launchSettings.json │ ├── appsettings.json │ ├── chatui.csproj │ ├── Program.cs │ └── Views │ └── Home │ └── Index.cshtml ├── docs └── media │ ├── basic-architecture.vsdx │ └── basic-architecture.svg ├── infra-as-code └── bicep │ ├── customerUsageAttribution │ └── cuaIdResourceGroup.bicep │ ├── bing-grounding.bicep │ ├── application-insights.bicep │ ├── ai-foundry-project.bicep │ ├── ai-foundry.bicep │ ├── main.bicep │ └── web-app.bicep ├── .github ├── CODE_OF_CONDUCT.md ├── dependabot.yml ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .devcontainer └── devcontainer.json ├── LICENSE.md ├── SECURITY.md ├── CONTRIBUTING.md ├── .gitignore └── README.md /website/chatui.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/openai-end-to-end-basic/HEAD/website/chatui.zip -------------------------------------------------------------------------------- /docs/media/basic-architecture.vsdx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/openai-end-to-end-basic/HEAD/docs/media/basic-architecture.vsdx -------------------------------------------------------------------------------- /website/chatui/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/openai-end-to-end-basic/HEAD/website/chatui/wwwroot/favicon.ico -------------------------------------------------------------------------------- /website/chatui/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | 3 | namespace chatui.Controllers; 4 | 5 | public class HomeController : Controller 6 | { 7 | public IActionResult Index() 8 | { 9 | return View(); 10 | } 11 | } -------------------------------------------------------------------------------- /infra-as-code/bicep/customerUsageAttribution/cuaIdResourceGroup.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'resourceGroup' 2 | 3 | // This is an empty deployment by design 4 | // Reference: https://learn.microsoft.com/partner-center/marketplace-offers/azure-partner-customer-usage-attribution 5 | -------------------------------------------------------------------------------- /website/chatui/Configuration/ChatApiOptions.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace chatui.Configuration; 4 | 5 | public class ChatApiOptions 6 | { 7 | [Url] 8 | public string AIProjectEndpoint { get; init; } = default!; 9 | 10 | [Required] 11 | public string AIAgentId { get; init; } = default!; 12 | } -------------------------------------------------------------------------------- /infra-as-code/bicep/bing-grounding.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'resourceGroup' 2 | 3 | #disable-next-line BCP081 4 | resource bingAccount 'Microsoft.Bing/accounts@2025-05-01-preview' = { 5 | name: 'bing-ai-agent' 6 | location: 'global' 7 | kind: 'Bing.Grounding' 8 | sku: { 9 | name: 'G1' 10 | } 11 | } 12 | 13 | output bingAccountName string = bingAccount.name 14 | -------------------------------------------------------------------------------- /website/chatui/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "http": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "launchUrl": "Home", 9 | "applicationUrl": "http://localhost:5064", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /website/chatui/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | }, 7 | "Console": { 8 | "LogLevel": { 9 | "Default": "Debug", 10 | "Microsoft": "Warning" 11 | } 12 | } 13 | }, 14 | "AllowedHosts": "*", 15 | "AIProjectEndpoint": "https://.services.ai.azure.com/api/projects/", 16 | "AIAgentId": "" 17 | } -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /website/chatui/chatui.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net8.0 4 | enable 5 | enable 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "nuget" # See documentation for possible values 9 | directory: "/website/chatui" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "AI Agent service chat basic reference implementation", 3 | "image": "mcr.microsoft.com/devcontainers/dotnet:dev-8.0-jammy", 4 | "runArgs": ["--network=host"], 5 | "remoteUser": "vscode", 6 | "features": { 7 | "ghcr.io/devcontainers/features/azure-cli:1": {} 8 | }, 9 | "customizations": { 10 | "vscode": { 11 | "extensions": [ 12 | "ms-dotnettools.csdevkit", 13 | "ms-azuretools.vscode-bicep" 14 | ], 15 | "settings": {} 16 | } 17 | }, 18 | "forwardPorts": [] 19 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | > Please provide us with the following information: 5 | > --------------------------------------------------------------- 6 | 7 | ### This issue is for a: (mark with an `x`) 8 | ``` 9 | - [ ] bug report -> please search issues before submitting 10 | - [ ] feature request 11 | - [ ] documentation issue or request 12 | - [ ] regression (a behavior that used to work and stopped in a new release) 13 | ``` 14 | 15 | ### Minimal steps to reproduce 16 | > 17 | 18 | ### Any log messages given by the failure 19 | > 20 | 21 | ### Expected/desired behavior 22 | > 23 | 24 | ### OS and Version? 25 | > Windows 7, 8 or 10. Linux (which distribution). macOS (Yosemite? El Capitan? Sierra?) 26 | 27 | ### Versions 28 | > 29 | 30 | ### Mention any other details that might be useful 31 | 32 | > --------------------------------------------------------------- 33 | > Thanks! We'll be in touch soon. 34 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | * ... 4 | 5 | ## Does this introduce a breaking change? 6 | 7 | ``` 8 | [ ] Yes 9 | [ ] No 10 | ``` 11 | 12 | ## Pull Request Type 13 | What kind of change does this Pull Request introduce? 14 | 15 | 16 | ``` 17 | [ ] Bugfix 18 | [ ] Feature 19 | [ ] Code style update (formatting, local variables) 20 | [ ] Refactoring (no functional changes, no api changes) 21 | [ ] Documentation content changes 22 | [ ] Other... Please describe: 23 | ``` 24 | 25 | ## How to Test 26 | * Get the code 27 | 28 | ``` 29 | git clone [repo-address] 30 | cd [repo-name] 31 | git checkout [branch-name] 32 | npm install 33 | ``` 34 | 35 | * Test the code 36 | 37 | ``` 38 | ``` 39 | 40 | ## What to Check 41 | Verify that the following are valid 42 | * ... 43 | 44 | ## Other Information 45 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE -------------------------------------------------------------------------------- /website/chatui/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Options; 2 | using Azure.AI.Agents.Persistent; 3 | using Azure.Identity; 4 | using chatui.Configuration; 5 | 6 | var builder = WebApplication.CreateBuilder(args); 7 | 8 | builder.Services.AddOptions() 9 | .Bind(builder.Configuration) 10 | .ValidateDataAnnotations() 11 | .ValidateOnStart(); 12 | 13 | builder.Services.AddSingleton((provider) => 14 | { 15 | var config = provider.GetRequiredService>().Value; 16 | PersistentAgentsClient client = new(config.AIProjectEndpoint, new DefaultAzureCredential()); 17 | 18 | return client; 19 | }); 20 | 21 | builder.Services.AddControllersWithViews(); 22 | 23 | builder.Services.AddCors(options => 24 | { 25 | options.AddPolicy("AllowAllOrigins", 26 | builder => 27 | { 28 | builder.AllowAnyOrigin() 29 | .AllowAnyMethod() 30 | .AllowAnyHeader(); 31 | }); 32 | }); 33 | 34 | var app = builder.Build(); 35 | 36 | app.UseStaticFiles(); 37 | 38 | app.UseRouting(); 39 | 40 | app.MapControllerRoute( 41 | name: "default", 42 | pattern: "{controller=Home}/{action=Index}/{id?}"); 43 | 44 | app.UseCors("AllowAllOrigins"); 45 | 46 | app.Run(); -------------------------------------------------------------------------------- /infra-as-code/bicep/application-insights.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'resourceGroup' 2 | 3 | @description('The region in which this architecture is deployed. Should match the region of the resource group.') 4 | @minLength(1) 5 | param location string = resourceGroup().location 6 | 7 | @description('This is the base name for each Azure resource name (6-8 chars)') 8 | @minLength(6) 9 | @maxLength(8) 10 | param baseName string 11 | 12 | @description('The name of the workload\'s existing Log Analytics workspace.') 13 | @minLength(4) 14 | param logAnalyticsWorkspaceName string 15 | 16 | // ---- Existing resources ---- 17 | 18 | resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2025-02-01' existing = { 19 | name: logAnalyticsWorkspaceName 20 | } 21 | 22 | // ---- New resources ---- 23 | 24 | resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { 25 | name: 'appi-${baseName}' 26 | location: location 27 | kind: 'web' 28 | properties: { 29 | Application_Type: 'web' 30 | WorkspaceResourceId: logAnalyticsWorkspace.id 31 | RetentionInDays: 90 32 | IngestionMode: 'LogAnalytics' 33 | publicNetworkAccessForIngestion: 'Enabled' 34 | publicNetworkAccessForQuery: 'Enabled' 35 | } 36 | } 37 | 38 | // ---- Outputs ---- 39 | 40 | output applicationInsightsName string = applicationInsights.name 41 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), and [Xamarin](https://github.com/xamarin). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /website/chatui/Controllers/ChatController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.Extensions.Options; 3 | using Azure; 4 | using Azure.AI.Agents.Persistent; 5 | using chatui.Configuration; 6 | 7 | namespace chatui.Controllers; 8 | 9 | [ApiController] 10 | [Route("[controller]/[action]")] 11 | 12 | public class ChatController( 13 | PersistentAgentsClient client, 14 | IOptionsMonitor options, 15 | ILogger logger) : ControllerBase 16 | { 17 | private readonly PersistentAgentsClient _client = client; 18 | private readonly IOptionsMonitor _options = options; 19 | private readonly ILogger _logger = logger; 20 | 21 | // TODO: [security] Do not trust client to provide threadId. Instead map current user to their active threadid in your application's own state store. 22 | // Without this security control in place, a user can inject messages into another user's thread. 23 | [HttpPost("{threadId}")] 24 | public async Task Completions([FromRoute] string threadId, [FromBody] string prompt) 25 | { 26 | if (string.IsNullOrWhiteSpace(prompt)) 27 | throw new ArgumentException("Prompt cannot be null, empty, or whitespace.", nameof(prompt)); 28 | 29 | _logger.LogDebug("Prompt received {Prompt}", prompt); 30 | var _config = _options.CurrentValue; 31 | 32 | PersistentThreadMessage message = await _client.Messages.CreateMessageAsync( 33 | threadId, 34 | MessageRole.User, 35 | prompt); 36 | 37 | ThreadRun run = await _client.Runs.CreateRunAsync(threadId, _config.AIAgentId); 38 | 39 | while (run.Status == RunStatus.Queued || run.Status == RunStatus.InProgress || run.Status == RunStatus.RequiresAction) 40 | { 41 | await Task.Delay(TimeSpan.FromMilliseconds(500)); 42 | run = (await _client.Runs.GetRunAsync(threadId, run.Id)).Value; 43 | } 44 | 45 | Pageable messages = _client.Messages.GetMessages( 46 | threadId: threadId, order: ListSortOrder.Ascending); 47 | 48 | var fullText = 49 | messages 50 | .Where(m => m.Role == MessageRole.Agent) 51 | .SelectMany(m => m.ContentItems.OfType()) 52 | .Last().Text; 53 | 54 | return Ok(new { data = fullText }); 55 | } 56 | 57 | [HttpPost] 58 | public async Task Threads() 59 | { 60 | // TODO [performance efficiency] Delay creating a thread until the first user message arrives. 61 | PersistentAgentThread thread = await _client.Threads.CreateThreadAsync(); 62 | 63 | return Ok(new { id = thread.Id }); 64 | } 65 | } -------------------------------------------------------------------------------- /infra-as-code/bicep/ai-foundry-project.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'resourceGroup' 2 | 3 | @description('The region in which this architecture is deployed. Should match the region of the resource group.') 4 | @minLength(1) 5 | param location string = resourceGroup().location 6 | 7 | @description('The existing Microsoft Foundry account. This project will become a child resource of this account.') 8 | @minLength(2) 9 | param existingFoundryName string 10 | 11 | @description('The existing Bing grounding data account that is available to Foundry agents in this project.') 12 | @minLength(1) 13 | param existingBingAccountName string 14 | 15 | @description('The existing Application Insights instance to log token usage in this project.') 16 | @minLength(1) 17 | param existingWebApplicationInsightsResourceName string 18 | 19 | // ---- Existing resources ---- 20 | 21 | #disable-next-line BCP081 22 | resource bingAccount 'Microsoft.Bing/accounts@2025-05-01-preview' existing = { 23 | name: existingBingAccountName 24 | } 25 | 26 | resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = { 27 | name: existingWebApplicationInsightsResourceName 28 | } 29 | 30 | // ---- New resources ---- 31 | 32 | @description('Existing Microsoft Foundry account. The project will be created as a child resource of this account.') 33 | resource foundry 'Microsoft.CognitiveServices/accounts@2025-06-01' existing = { 34 | name: existingFoundryName 35 | 36 | resource project 'projects' = { 37 | name: 'projchat' 38 | location: location 39 | identity: { 40 | type: 'SystemAssigned' 41 | } 42 | properties: { 43 | description: 'Chat using internet data in your Foundry agent.' 44 | displayName: 'Chat with Internet Data' 45 | } 46 | 47 | @description('Connect this project to application insights for visualization of token usage.') 48 | resource applicationInsightsConnection 'connections' = { 49 | name:'appInsights-connection' 50 | properties: { 51 | authType: 'ApiKey' 52 | category: 'AppInsights' 53 | credentials: { 54 | key: applicationInsights.properties.ConnectionString 55 | } 56 | isSharedToAll: false 57 | target: applicationInsights.id 58 | metadata: { 59 | ApiType: 'Azure' 60 | ResourceId: applicationInsights.id 61 | location: applicationInsights.location 62 | } 63 | } 64 | } 65 | 66 | @description('Create project connection to Bing grounding data. Useful for future agents that get created.') 67 | resource bingGroundingConnection 'connections' = { 68 | name: replace(existingBingAccountName, '-', '') 69 | properties: { 70 | authType: 'ApiKey' 71 | target: bingAccount.properties.endpoint 72 | category: 'GroundingWithBingSearch' 73 | metadata: { 74 | type: 'bing_grounding' 75 | ApiType: 'Azure' 76 | ResourceId: bingAccount.id 77 | location: bingAccount.location 78 | } 79 | credentials: { 80 | key: bingAccount.listKeys().key1 81 | } 82 | isSharedToAll: false 83 | } 84 | dependsOn: [ 85 | applicationInsightsConnection // Single thread changes to the project, else conflict errors tend to happen 86 | ] 87 | } 88 | } 89 | } 90 | 91 | // ---- Outputs ---- 92 | 93 | output aiAgentProjectName string = foundry::project.name 94 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Foundry Agent Service chat basic reference implementation 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit . 4 | 5 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. 6 | 7 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 8 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 9 | 10 | - [Code of Conduct](#coc) 11 | - [Issues and Bugs](#issue) 12 | - [Feature Requests](#feature) 13 | - [Submission Guidelines](#submit) 14 | 15 | ## Code of Conduct 16 | 17 | Help us keep this project open and inclusive. Please read and follow our [Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 18 | 19 | ## Found an Issue? 20 | 21 | If you find a bug in the source code or a mistake in the documentation, you can help us by [submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can [submit a Pull Request](#submit-pr) with a fix. 22 | 23 | ## Want a Feature? 24 | 25 | You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub Repository. If you would like to *implement* a new feature, please submit an issue with a proposal for your work first, to be sure that we can use it. 26 | 27 | - **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). 28 | 29 | ## Submission Guidelines 30 | 31 | ### Submitting an Issue 32 | 33 | Before you submit an issue, search the archive, maybe your question was already answered. 34 | 35 | If your issue appears to be a bug, and hasn't been reported, open a new issue. Help us to maximize the effort we can spend fixing issues and adding new features, by not reporting duplicate issues. Providing the following information will increase the chances of your issue being dealt with quickly: 36 | 37 | - **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps 38 | - **Version** - what version is affected (e.g. 0.1.2) 39 | - **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you 40 | - **Browsers and Operating System** - is this a problem with all browsers? 41 | - **Reproduce the Error** - provide a live example or a unambiguous set of steps 42 | - **Related Issues** - has a similar issue been reported before? 43 | - **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be causing the problem (line of code or commit) 44 | 45 | You can file new issues by providing the above information at the corresponding repository's issues link: . 46 | 47 | ### Submitting a Pull Request (PR) 48 | 49 | Before you submit your Pull Request (PR) consider the following guidelines: 50 | 51 | - Search the [repository](https://github.com/Azure-Samples/microsoft-foundry-basic/pulls) for an open or closed PR that relates to your submission. You don't want to duplicate effort. 52 | 53 | - Make your changes in a new git fork: 54 | 55 | - Commit your changes using a descriptive commit message 56 | - Push your fork to GitHub: 57 | - In GitHub, create a pull request 58 | - If we suggest changes then: 59 | - Make the required updates. 60 | - Rebase your fork and force push to your GitHub repository (this will update your Pull Request): 61 | 62 | ```shell 63 | git rebase main -i 64 | git push -f 65 | ``` 66 | 67 | That's it! Thank you for your contribution! 68 | -------------------------------------------------------------------------------- /infra-as-code/bicep/ai-foundry.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'resourceGroup' 2 | 3 | @description('The region in which this architecture is deployed. Should match the region of the resource group.') 4 | @minLength(1) 5 | param location string = resourceGroup().location 6 | 7 | @description('This is the base name for each Azure resource name (6-8 chars)') 8 | @minLength(6) 9 | @maxLength(8) 10 | param baseName string 11 | 12 | @description('The name of the workload\'s existing Log Analytics workspace.') 13 | @minLength(4) 14 | param logAnalyticsWorkspaceName string 15 | 16 | @description('Your principal ID. Allows you to access the Foundry portal for post-deployment verification of functionality.') 17 | @maxLength(36) 18 | @minLength(36) 19 | param foundryPortalUserPrincipalId string 20 | 21 | var foundryName = 'aif${baseName}' 22 | 23 | // ---- Existing resources ---- 24 | 25 | @description('Existing: Built-in Cognitive Services User role.') 26 | resource cognitiveServicesUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { 27 | name: 'a97b65f3-24c7-4388-baec-2e87135dc908' 28 | scope: subscription() 29 | } 30 | 31 | @description('Existing: Log sink for Azure Diagnostics.') 32 | resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2025-02-01' existing = { 33 | name: logAnalyticsWorkspaceName 34 | } 35 | 36 | // ---- New resources ---- 37 | 38 | @description('Deploy foundry (account) with Foundry Agent Service capability.') 39 | resource foundry 'Microsoft.CognitiveServices/accounts@2025-06-01' = { 40 | name: foundryName 41 | location: location 42 | kind: 'AIServices' 43 | sku: { 44 | name: 'S0' 45 | } 46 | identity: { 47 | type: 'SystemAssigned' 48 | } 49 | properties: { 50 | customSubDomainName: foundryName 51 | allowProjectManagement: true // Microsoft Foundry account + projects 52 | disableLocalAuth: true 53 | networkAcls: { 54 | bypass: 'AzureServices' 55 | ipRules: [] 56 | defaultAction: 'Allow' 57 | virtualNetworkRules: [] 58 | } 59 | publicNetworkAccess: 'Enabled' 60 | } 61 | 62 | @description('Models are managed at the account level. Deploy the GPT model that will be used for the Foundry agent logic.') 63 | resource model 'deployments' = { 64 | name: 'agent-model' 65 | sku: { 66 | capacity: 50 67 | name: 'GlobalStandard' 68 | } 69 | properties: { 70 | model: { 71 | format: 'OpenAI' 72 | name: 'gpt-4o' 73 | version: '2024-11-20' // Use a model version available in your region. 74 | } 75 | versionUpgradeOption: 'NoAutoUpgrade' // Production deployments should not auto-upgrade models. Testing compatibility is important. 76 | } 77 | } 78 | } 79 | 80 | // Role assignments 81 | 82 | @description('Assign yourself to have access to the Foundry portal.') 83 | resource cognitiveServicesUser 'Microsoft.Authorization/roleAssignments@2022-04-01' = { 84 | name: guid(foundry.id, cognitiveServicesUserRole.id, foundryPortalUserPrincipalId) 85 | scope: foundry 86 | properties: { 87 | roleDefinitionId: cognitiveServicesUserRole.id 88 | principalId: foundryPortalUserPrincipalId 89 | principalType: 'User' 90 | } 91 | } 92 | 93 | // Azure diagnostics 94 | 95 | @description('Enable logging on the Foundry account.') 96 | resource azureDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { 97 | name: 'default' 98 | scope: foundry 99 | properties: { 100 | workspaceId: logAnalyticsWorkspace.id 101 | logs: [ 102 | { 103 | category: 'Audit' 104 | enabled: true 105 | retentionPolicy: { 106 | enabled: false 107 | days: 0 108 | } 109 | } 110 | { 111 | category: 'RequestResponse' 112 | enabled: true 113 | retentionPolicy: { 114 | enabled: false 115 | days: 0 116 | } 117 | } 118 | { 119 | category: 'AzureOpenAIRequestUsage' 120 | enabled: true 121 | retentionPolicy: { 122 | enabled: false 123 | days: 0 124 | } 125 | } 126 | { 127 | category: 'Trace' 128 | enabled: true 129 | retentionPolicy: { 130 | enabled: false 131 | days: 0 132 | } 133 | } 134 | ] 135 | } 136 | } 137 | 138 | // ---- Outputs ---- 139 | 140 | @description('The name of the Microsoft Foundry account.') 141 | output foundryName string = foundry.name 142 | -------------------------------------------------------------------------------- /infra-as-code/bicep/main.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'resourceGroup' 2 | 3 | @description('The region in which this architecture is deployed. Should match the region of the resource group.') 4 | @minLength(1) 5 | param location string = resourceGroup().location 6 | 7 | @description('This is the base name for each Azure resource name (6-8 chars)') 8 | @minLength(6) 9 | @maxLength(8) 10 | param baseName string 11 | 12 | @description('Assign your user some roles to support fluid access when working in the Foundry portal and its dependencies.') 13 | @maxLength(36) 14 | @minLength(36) 15 | param yourPrincipalId string 16 | 17 | @description('Set to true to opt-out of deployment telemetry.') 18 | param telemetryOptOut bool = false 19 | 20 | // Customer Usage Attribution Id 21 | var varCuaid = '6aa4564a-a8b7-4ced-8e57-1043a41f4747' 22 | 23 | // ---- New resources ---- 24 | 25 | @description('This is the log sink for all Azure Diagnostics in the workload.') 26 | resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { 27 | name: 'log-workload' 28 | location: location 29 | properties: { 30 | sku: { 31 | name: 'PerGB2018' 32 | } 33 | retentionInDays: 30 34 | forceCmkForQuery: false 35 | workspaceCapping: { 36 | dailyQuotaGb: 10 // Production readiness change: In production, tune this value to ensure operational logs are collected, but a reasonable cap is set. 37 | } 38 | publicNetworkAccessForIngestion: 'Enabled' 39 | publicNetworkAccessForQuery: 'Enabled' 40 | } 41 | } 42 | 43 | // Deploy the Microsoft Foundry account and Foundry Agent Service components. 44 | 45 | @description('Deploy Microsoft Foundry with Foundry Agent Service capability. No projects yet deployed.') 46 | module deployFoundry 'ai-foundry.bicep' = { 47 | scope: resourceGroup() 48 | name: 'foundryDeploy' 49 | params: { 50 | location: location 51 | baseName: baseName 52 | logAnalyticsWorkspaceName: logAnalyticsWorkspace.name 53 | foundryPortalUserPrincipalId: yourPrincipalId 54 | } 55 | } 56 | 57 | @description('Deploy the Bing account for Internet grounding data to be used by agents in the Foundry Agent Service.') 58 | module deployBingAccount 'bing-grounding.bicep' = { 59 | scope: resourceGroup() 60 | name: 'bingAccountDeploy' 61 | } 62 | 63 | @description('Deploy the Foundry project into the Foundry account. This is the project is the home of the Foundry Agent Service.') 64 | module deployFoundryProject 'ai-foundry-project.bicep' = { 65 | scope: resourceGroup() 66 | name: 'foundryProjectDeploy' 67 | params: { 68 | location: location 69 | existingFoundryName: deployFoundry.outputs.foundryName 70 | existingBingAccountName: deployBingAccount.outputs.bingAccountName 71 | existingWebApplicationInsightsResourceName: deployApplicationInsights.outputs.applicationInsightsName 72 | } 73 | } 74 | 75 | // Deploy the Azure Web App resources for the chat UI. 76 | 77 | @description('Deploy Application Insights. Used by the Azure Web App to monitor the deployed application and connected to the Foundry project.') 78 | module deployApplicationInsights 'application-insights.bicep' = { 79 | scope: resourceGroup() 80 | name: 'applicationInsightsDeploy' 81 | params: { 82 | location: location 83 | baseName: baseName 84 | logAnalyticsWorkspaceName: logAnalyticsWorkspace.name 85 | } 86 | } 87 | 88 | @description('Deploy the web app for the front end demo UI. The web application will call into the Foundry Agent Service.') 89 | module deployWebApp 'web-app.bicep' = { 90 | scope: resourceGroup() 91 | name: 'webAppDeploy' 92 | params: { 93 | location: location 94 | baseName: baseName 95 | logAnalyticsWorkspaceName: logAnalyticsWorkspace.name 96 | existingWebApplicationInsightsResourceName: deployApplicationInsights.outputs.applicationInsightsName 97 | existingFoundryResourceName: deployFoundry.outputs.foundryName 98 | existingFoundryProjectName: deployFoundryProject.outputs.aiAgentProjectName 99 | } 100 | } 101 | 102 | // Optional Deployment for Customer Usage Attribution 103 | module customerUsageAttributionModule 'customerUsageAttribution/cuaIdResourceGroup.bicep' = if (!telemetryOptOut) { 104 | #disable-next-line no-loc-expr-outside-params // Only to ensure telemetry data is stored in same location as deployment. See https://github.com/Azure/ALZ-Bicep/wiki/FAQ#why-are-some-linter-rules-disabled-via-the-disable-next-line-bicep-function for more information 105 | name: 'pid-${varCuaid}-${uniqueString(resourceGroup().location)}' 106 | scope: resourceGroup() 107 | params: {} 108 | } 109 | -------------------------------------------------------------------------------- /infra-as-code/bicep/web-app.bicep: -------------------------------------------------------------------------------- 1 | targetScope = 'resourceGroup' 2 | 3 | /* 4 | Deploy a web app with a managed identity, diagnostic, and a private endpoint 5 | */ 6 | 7 | @description('This is the base name for each Azure resource name (6-8 chars)') 8 | @minLength(6) 9 | @maxLength(8) 10 | param baseName string 11 | 12 | @description('The region in which this architecture is deployed. Should match the region of the resource group.') 13 | @minLength(1) 14 | param location string = resourceGroup().location 15 | 16 | @description('The name of the workload\'s existing Log Analytics workspace.') 17 | @minLength(4) 18 | param logAnalyticsWorkspaceName string 19 | 20 | @description('The name of the existing Azure Application Insights instance that the Azure Web App will be using.') 21 | @minLength(1) 22 | param existingWebApplicationInsightsResourceName string 23 | 24 | @description('The name of the existing Microsoft Foundry instance that the Azure Web App code will be calling for Foundry Agent Service agents.') 25 | @minLength(2) 26 | param existingFoundryResourceName string 27 | 28 | @description('The name of the existing Foundry project name.') 29 | @minLength(2) 30 | param existingFoundryProjectName string 31 | 32 | // variables 33 | var appName = 'app-${baseName}' 34 | 35 | // ---- Existing resources ---- 36 | 37 | @description('Existing Application Insights instance. Logs from the web app will be sent here.') 38 | resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = { 39 | name: existingWebApplicationInsightsResourceName 40 | } 41 | 42 | resource logWorkspace 'Microsoft.OperationalInsights/workspaces@2025-02-01' existing = { 43 | name: logAnalyticsWorkspaceName 44 | } 45 | 46 | @description('Built-in Role: [Azure AI User](https://learn.microsoft.com/azure/ai-foundry/concepts/rbac-azure-ai-foundry?pivots=fdp-project#azure-ai-user)') 47 | resource azureAiUserRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { 48 | name: '53ca6127-db72-4b80-b1b0-d745d6d5456d' 49 | scope: subscription() 50 | } 51 | 52 | @description('Existing Foundry account. This account is where the agents hosted in Foundry Agent Service will be deployed. The web app code calls to these agents.') 53 | resource foundry 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = { 54 | name: existingFoundryResourceName 55 | 56 | resource project 'projects' existing = { 57 | name: existingFoundryProjectName 58 | } 59 | } 60 | 61 | // ---- New resources ---- 62 | 63 | @description('Managed Identity for App Service') 64 | resource appServiceManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = { 65 | name: 'id-${appName}' 66 | location: location 67 | } 68 | 69 | @description('Grant the App Service managed identity Azure AI user role permission so it can call into the Foundry-hosted agent.') 70 | resource azureAiUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { 71 | scope: foundry 72 | name: guid(foundry.id, appServiceManagedIdentity.id, azureAiUserRole.id) 73 | properties: { 74 | roleDefinitionId: azureAiUserRole.id 75 | principalType: 'ServicePrincipal' 76 | principalId: appServiceManagedIdentity.properties.principalId 77 | } 78 | } 79 | 80 | @description('Linux, B1 App Service Plan to host the chat web application.') 81 | resource appServicePlan 'Microsoft.Web/serverfarms@2024-04-01' = { 82 | name: 'asp-${appName}${uniqueString(subscription().subscriptionId)}' 83 | location: location 84 | kind: 'linux' 85 | sku: { 86 | name: 'B1' // az appservice list-locations --linux-workers-enabled --sku B1 87 | tier: 'Basic' 88 | capacity: 1 89 | } 90 | properties: { 91 | zoneRedundant: false 92 | reserved: true 93 | } 94 | } 95 | 96 | @description('This is the web app that contains the chat UI application.') 97 | resource webApp 'Microsoft.Web/sites@2024-04-01' = { 98 | name: appName 99 | location: location 100 | kind: 'app,linux' 101 | identity: { 102 | type: 'UserAssigned' 103 | userAssignedIdentities: { 104 | '${appServiceManagedIdentity.id}': {} 105 | } 106 | } 107 | properties: { 108 | enabled: true 109 | serverFarmId: appServicePlan.id 110 | virtualNetworkSubnetId: null 111 | httpsOnly: true 112 | #disable-next-line BCP037 // This is a valid property, just not part of the schema https://github.com/Azure/bicep-types-az/issues/2204 113 | sshEnabled: false 114 | autoGeneratedDomainNameLabelScope: 'SubscriptionReuse' 115 | vnetContentShareEnabled: false 116 | vnetImagePullEnabled: false 117 | publicNetworkAccess: 'Enabled' 118 | keyVaultReferenceIdentity: null 119 | endToEndEncryptionEnabled: true 120 | vnetRouteAllEnabled: false 121 | hostNamesDisabled: false 122 | clientAffinityEnabled: false 123 | siteConfig: { 124 | ftpsState: 'Disabled' 125 | vnetRouteAllEnabled: false 126 | http20Enabled: false 127 | publicNetworkAccess: 'Enabled' 128 | alwaysOn: true 129 | linuxFxVersion: 'DOTNETCORE|8.0' 130 | netFrameworkVersion: null 131 | windowsFxVersion: null 132 | } 133 | } 134 | dependsOn: [] 135 | 136 | @description('Default configuration for the web app.') 137 | resource appsettings 'config' = { 138 | name: 'appsettings' 139 | properties: { 140 | APPLICATIONINSIGHTS_CONNECTION_STRING: applicationInsights.properties.ConnectionString 141 | AZURE_CLIENT_ID: appServiceManagedIdentity.properties.clientId 142 | ApplicationInsightsAgent_EXTENSION_VERSION: '~3' 143 | AIProjectEndpoint: foundry::project.properties.endpoints['AI Foundry API'] 144 | AIAgentId: 'Not yet set' // Will be set once the agent is created 145 | XDT_MicrosoftApplicationInsights_Mode: 'Recommended' 146 | } 147 | } 148 | 149 | @description('Disable SCM publishing integration.') 150 | resource scm 'basicPublishingCredentialsPolicies' = { 151 | name: 'scm' 152 | properties: { 153 | allow: false 154 | } 155 | } 156 | 157 | @description('Disable FTP publishing integration.') 158 | resource ftp 'basicPublishingCredentialsPolicies' = { 159 | name: 'ftp' 160 | properties: { 161 | allow: false 162 | } 163 | } 164 | } 165 | 166 | @description('Enable App Service Azure Diagnostic') 167 | resource azureDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { 168 | name: 'default' 169 | scope: webApp 170 | properties: { 171 | workspaceId: logWorkspace.id 172 | logs: [ 173 | { 174 | category: 'AppServiceHTTPLogs' 175 | enabled: true 176 | } 177 | { 178 | category: 'AppServiceConsoleLogs' 179 | enabled: true 180 | } 181 | { 182 | category: 'AppServiceAppLogs' 183 | enabled: true 184 | } 185 | { 186 | category: 'AppServicePlatformLogs' 187 | enabled: true 188 | } 189 | { 190 | category: 'AppServiceAuditLogs' 191 | enabled: true 192 | } 193 | { 194 | category: 'AppServiceIPSecAuditLogs' 195 | enabled: true 196 | } 197 | { 198 | category: 'AppServiceAuthenticationLogs' 199 | enabled: true 200 | } 201 | ] 202 | } 203 | } 204 | 205 | // ---- Outputs ---- 206 | 207 | @description('The name of the app service plan.') 208 | output appServicePlanName string = appServicePlan.name 209 | 210 | @description('The name of the web app.') 211 | output appName string = webApp.name 212 | -------------------------------------------------------------------------------- /website/chatui/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 173 | 174 | 266 | 267 | 268 | 269 |
270 |
271 |

272 | 273 | Chat with your orchestrator 274 |

275 |
276 | 277 |
278 | 279 |
280 | 281 |
282 | 292 | 293 |
294 |
295 | 296 | 297 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 298 | *.vbp 299 | 300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 301 | *.dsw 302 | *.dsp 303 | 304 | # Visual Studio 6 technical files 305 | *.ncb 306 | *.aps 307 | 308 | # Visual Studio LightSwitch build output 309 | **/*.HTMLClient/GeneratedArtifacts 310 | **/*.DesktopClient/GeneratedArtifacts 311 | **/*.DesktopClient/ModelManifest.xml 312 | **/*.Server/GeneratedArtifacts 313 | **/*.Server/ModelManifest.xml 314 | _Pvt_Extensions 315 | 316 | # Paket dependency manager 317 | .paket/paket.exe 318 | paket-files/ 319 | 320 | # FAKE - F# Make 321 | .fake/ 322 | 323 | # CodeRush personal settings 324 | .cr/personal 325 | 326 | # Python Tools for Visual Studio (PTVS) 327 | __pycache__/ 328 | *.pyc 329 | 330 | # Cake - Uncomment if you are using it 331 | # tools/** 332 | # !tools/packages.config 333 | 334 | # Tabs Studio 335 | *.tss 336 | 337 | # Telerik's JustMock configuration file 338 | *.jmconfig 339 | 340 | # BizTalk build output 341 | *.btp.cs 342 | *.btm.cs 343 | *.odx.cs 344 | *.xsd.cs 345 | 346 | # OpenCover UI analysis results 347 | OpenCover/ 348 | 349 | # Azure Stream Analytics local run output 350 | ASALocalRun/ 351 | 352 | # MSBuild Binary and Structured Log 353 | *.binlog 354 | 355 | # NVidia Nsight GPU debugger configuration file 356 | *.nvuser 357 | 358 | # MFractors (Xamarin productivity tool) working folder 359 | .mfractor/ 360 | 361 | # Local History for Visual Studio 362 | .localhistory/ 363 | 364 | # Visual Studio History (VSHistory) files 365 | .vshistory/ 366 | 367 | # BeatPulse healthcheck temp database 368 | healthchecksdb 369 | 370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 371 | MigrationBackup/ 372 | 373 | # Ionide (cross platform F# VS Code tools) working folder 374 | .ionide/ 375 | 376 | # Fody - auto-generated XML schema 377 | FodyWeavers.xsd 378 | 379 | # VS Code files for those working on multiple tools 380 | .vscode/* 381 | !.vscode/settings.json 382 | !.vscode/tasks.json 383 | !.vscode/launch.json 384 | !.vscode/extensions.json 385 | *.code-workspace 386 | 387 | # Local History for Visual Studio Code 388 | .history/ 389 | 390 | # Windows Installer files from build outputs 391 | *.cab 392 | *.msi 393 | *.msix 394 | *.msm 395 | *.msp 396 | 397 | # JetBrains Rider 398 | *.sln.iml 399 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Foundry Agent Service chat basic reference implementation 2 | 3 | This reference implementation illustrates an approach running a chat application and an AI orchestration layer in a single region. It uses Foundry Agent Service as the orchestrator and Azure OpenAI foundation models. This repository directly supports the [Basic end-to-end chat reference architecture](https://learn.microsoft.com/azure/architecture/ai-ml/architecture/basic-openai-e2e-chat) on Microsoft Learn. 4 | 5 | The reference implementation illustrates a basic example of a chat application. For a reference implementation that implements more enterprise requirements, please see the [Microsoft Foundry Agent Service baseline reference implementation](https://github.com/Azure-Samples/openai-end-to-end-baseline). That implementation addresses many of the [production readiness changes](https://github.com/search?q=repo%3AAzure-Samples%2Fopenai-end-to-end-basic+%22Production+readiness+change%22&type=code) identified in this code. 6 | 7 | ## Architecture 8 | 9 | The implementation covers the following scenarios: 10 | 11 | - [Setting up Microsoft Foundry to host agents](#setting-up-microsoft-foundry-to-host-agents) 12 | - [Deploying an agent into Foundry Agent Service](#deploying-an-agent-into-foundry-agent-service) 13 | - [Invoking the agent from .NET code hosted in an Azure Web App](#invoking-the-agent-from-net-code-hosted-in-an-azure-web-app) 14 | 15 | ### Setting up Microsoft Foundry to host agents 16 | 17 | Microsoft Foundry hosts the Foundry Agent Service as a capability. Foundry Agent Service's REST APIs are exposed as an internet facing endpoint. 18 | 19 | ![Diagram that shows a basic chat architecture.](docs/media/basic-architecture.svg) 20 | 21 | *Download a [Visio file](docs/media/basic-architecture.vsdx) of this architecture.* 22 | 23 | #### Workflow 24 | 25 | The following workflow corresponds to the previous diagram: 26 | 27 | 1. An application user interacts with a web application that contains chat functionality. They issue an HTTPS request to the App Service default domain on azurewebsites.net. This domain automatically points to the App Service built-in public IP address. The Transport Layer Security connection is established from the client directly to App Service. Azure fully manages the certificate. 28 | 1. The App Service feature called Easy Auth ensures that the user who accesses the website is authenticated via Microsoft Entra ID. 29 | 1. The application code deployed to App Service handles the request and renders a chat UI for the application user. The chat UI code connects to APIs that are also hosted in that same App Service instance. The API code connects to an agent in Microsoft Foundry by using the Azure AI Persistent Agents SDK. 30 | 1. Foundry Agent Service connects to Azure AI Search to fetch grounding data for the query. The grounding data is added to the prompt that's sent to the Azure OpenAI model in the next step. 31 | 1. Foundry Agent Service connects to an Azure OpenAI model that's deployed in Foundry and sends the prompt that includes the relevant grounding data and chat context. 32 | 1. Application Insights logs information about the original request to App Service and the call agent interactions. 33 | 34 | ### Deploying an agent into Foundry Agent Service 35 | 36 | Agents can be created via the Foundry portal, [Azure AI Persistent Agents client library](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/ai/Azure.AI.Agents.Persistent), or the [REST API](https://learn.microsoft.com/rest/api/aifoundry/aiagents/). The creation and invocation of agents are a data plane operation. 37 | 38 | Ideally agents should be source-controlled and a versioned asset. You then can deploy agents in a coordinated way with the rest of your workload's code. In this deployment guide, you'll create an agent through the REST API to simulate a deployment pipeline which could have created the agent. 39 | 40 | ### Invoking the agent from .NET code hosted in an Azure Web App 41 | 42 | A chat UI application is deployed into Azure App Service. The .NET code uses the [Azure AI Persistent Agents client library](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/ai/Azure.AI.Agents.Persistent) to connect to the workload's agent. The endpoint for the agent is exposed over internet through Foundry. 43 | 44 | ## Deployment guide 45 | 46 | Follow these instructions to deploy this example to your Azure subscription, try out what you've deployed, and learn how to clean up those resources. 47 | 48 | ### Prerequisites 49 | 50 | - An [Azure subscription](https://azure.microsoft.com/free/) 51 | 52 | - The subscription must have all of the resource providers used in this deployment [registered](https://learn.microsoft.com/azure/azure-resource-manager/management/resource-providers-and-types#register-resource-provider). 53 | 54 | - `Microsoft.CognitiveServices` 55 | - `Microsoft.Insights` 56 | - `Microsoft.ManagedIdentity` 57 | - `Microsoft.OperationalInsights` 58 | - `Microsoft.Storage` 59 | 60 | - The subscription must have the following quota available in the region you choose. 61 | 62 | - App Service Plans: P1v3 (AZ), 3 instances 63 | - OpenAI model: GPT-4o model deployment with 50k tokens per minute (TPM) capacity 64 | 65 | - Your deployment user must have the following permissions at the subscription scope. 66 | 67 | - Ability to assign [Azure roles](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles) on newly created resource groups and resources. (E.g. `User Access Administrator` or `Owner`) 68 | - Ability to purge deleted AI services resources. (E.g. `Contributor` or `Cognitive Services Contributor`) 69 | 70 | - The [Azure CLI installed](https://learn.microsoft.com/cli/azure/install-azure-cli) 71 | 72 | If you're executing this from WSL, be sure the Azure CLI is installed in WSL and is not using the version installed in Windows. `which az` should show `/usr/bin/az`. 73 | 74 | ### 1. :rocket: Deploy the infrastructure 75 | 76 | The following steps are required to deploy the infrastructure from the command line. 77 | 78 | 1. In your shell, clone this repo and navigate to the root directory of this repository. 79 | 80 | ```bash 81 | git clone https://github.com/Azure-Samples/microsoft-foundry-basic 82 | cd microsoft-foundry-basic 83 | ``` 84 | 85 | 1. Log in and set your target subscription. 86 | 87 | ```bash 88 | az login 89 | az account set --subscription xxxxx 90 | ``` 91 | 92 | 1. Set the deployment location to one with available quota in your subscription. 93 | 94 | This deployment has been tested in the following locations: `australiaeast`, `eastus`, `eastus2`, `francecentral`, `japaneast`, `southcentralus`, `swedencentral`, `switzerlandnorth`, or `uksouth`. You might be successful in other locations as well. 95 | 96 | ```bash 97 | LOCATION=eastus2 98 | ``` 99 | 100 | 1. Set the base name value that will be used as part of the Azure resource names for the resources deployed in this solution. 101 | 102 | ```bash 103 | BASE_NAME= 104 | ``` 105 | 106 | 1. Create a resource group and deploy the infrastructure. 107 | 108 | *There is an optional tracking ID on this deployment. To opt out of its use, add the following parameter to the deployment code below: `-p telemetryOptOut true`.* 109 | 110 | ```bash 111 | RESOURCE_GROUP=rg-chat-basic-${BASE_NAME} 112 | az group create -l $LOCATION -n $RESOURCE_GROUP 113 | 114 | PRINCIPAL_ID=$(az ad signed-in-user show --query id -o tsv) 115 | 116 | # This takes about 10 minutes to run. 117 | az deployment group create -f ./infra-as-code/bicep/main.bicep \ 118 | -g $RESOURCE_GROUP \ 119 | -p baseName=${BASE_NAME} \ 120 | -p yourPrincipalId=$PRINCIPAL_ID 121 | ``` 122 | 123 | ### 2. Deploy an agent in the Foundry Agent Service 124 | 125 | To test this scenario, you'll be deploying a prompt-based AI agent. The agent uses a GPT model combined with a Bing search for grounding data. Deploying an AI agent requires data plane access to Microsoft Foundry. In this architecture, you will interact with the Foundry portal and its resources over the internet. 126 | 127 | 1. Open the Azure portal to your subscription. 128 | 129 | 1. Navigate to the Foundry project named **projchat** in your resource group and open the Foundry portal by clicking the **Go to Foundry portal** button. 130 | 131 | This will take you directly into the 'Chat project'. Alternatively, you can find all your Foundry accounts and projects by going to and you do not need to use the Azure portal to access them. 132 | 133 | 1. In the upper-right corner, if not already enabled, toggle **New Foundry** to switch into the Microsoft Foundry (new) portal. 134 | 135 | 1. In the top-right corner, click **Build**. This opens by default the **Agents** blade in the side navigation, where you can view the available agents and create new ones. 136 | 137 | The first time you access this section, the **Agents** list should be empty. 138 | 139 | 1. Click **Create agent** button. 140 | 141 | 1. From the Create an agent popup, enter 'baseline-chatbot-agent' as the Agent name. 142 | 143 | 1. From the Playground panel, select the available deployment model named **agent-model**. 144 | 145 | 1. Expand the Knowledge section, and click **Add** button. 146 | 147 | 1. From the drop down list select the option **+ Set up a data source via tools**. 148 | 149 | 1. From the popup window select the knowledge type 'Grounding with Bing Search'. 150 | 151 | 1. Click **Add tool**. 152 | 153 | 1. From the 'Grounding with Bing Search connection' drop down list choose the existing connection named 'bingaiagent', and click the **Add** button. 154 | 155 | 1. Click **Save** buton at the top-right of the Agents' Playground panel. 156 | 157 | ### 3. Test the agent from the Foundry portal in the playground 158 | 159 | Here you'll test your orchestration agent by invoking it directly from the Foundry portal agent playground chat experience. 160 | 161 | 1. Select the agent you just saved from the previous step named 'baseline-chatbot-agent'. 162 | 163 | 1. Enter a question to the agent that would require grounding data through recent internet content, such as a notable recent event or the weather today in your location. 164 | 165 | 1. A grounded response to your question should appear on the UI. 166 | 167 | ### 4. Publish the chat front-end web app 168 | 169 | Workloads build chat functionality into an application. Those interfaces usually call Foundry project endpoint invoking a particular agent. This implementation comes with such an interface. You'll deploy it to Azure App Service using the Azure CLI. 170 | 171 | 1. Generate some variables to set context. 172 | 173 | *The following variables align with the defaults in this deployment. Update them if you customized anything.* 174 | 175 | ```bash 176 | FOUNDRY_NAME="aif${BASE_NAME}" 177 | FOUNDRY_PROJECT_NAME="projchat" 178 | FOUNDRY_AGENT_CREATE_URL="https://${FOUNDRY_NAME}.services.ai.azure.com/api/projects/${FOUNDRY_PROJECT_NAME}/assistants?api-version=2025-05-15-preview" 179 | 180 | echo $FOUNDRY_AGENT_CREATE_URL 181 | ``` 182 | 183 | 1. Get Agent ID value. 184 | 185 | ```bash 186 | AGENT_ID=$(az rest -u $FOUNDRY_AGENT_CREATE_URL -m "get" --resource "https://ai.azure.com" --query 'data[0].id' -o tsv) 187 | 188 | echo $AGENT_ID 189 | ```` 190 | 191 | 1. Update the app configuration to use the agent you deployed. 192 | 193 | ```bash 194 | APPSERVICE_NAME=app-$BASE_NAME 195 | 196 | az webapp config appsettings set -g $RESOURCE_GROUP -n $APPSERVICE_NAME --settings AIAgentId=${AGENT_ID} 197 | ```` 198 | 199 | 1. Deploy the ChatUI web app 200 | 201 | ```bash 202 | az webapp deploy -g $RESOURCE_GROUP -n $APPSERVICE_NAME --type zip --src-url https://github.com/Azure-Samples/microsoft-foundry-basic/raw/refs/heads/main/website/chatui.zip 203 | ``` 204 | 205 | > Sometimes the prior command will fail with a `GatewayTimeout`. If you receive that error, you're safe to simply execute the command again. 206 | 207 | ### 5. Try it out! Test the deployed application that calls into the Foundry Agent Service 208 | 209 | After the deployment is complete, you can try the deployed application by navigating to the Web App's URL in a web browser. 210 | 211 | You can also execute the following from your workstation. Unfortunately, this command does not reliably work from Azure Cloud Shell. 212 | 213 | ```bash 214 | az webapp browse -g $RESOURCE_GROUP -n $APPSERVICE_NAME 215 | ``` 216 | 217 | Once you're there, ask your solution a question. Your question should involve something that would only be known if the RAG process included context from Bing such as recent weather or events. 218 | 219 | ## :broom: Clean up resources 220 | 221 | Most Azure resources deployed in the prior steps will incur ongoing charges unless removed. Additionally, a few of the resources deployed go into a soft delete status which will restrict the ability to redeploy another resource with the same name and might not release quota. It's best to purge any soft deleted resources once you are done exploring. Use the following commands to delete the deployed resources and resource group and to purge each of the resources with soft delete. 222 | 223 | > **Note:** This will completely delete any data you may have included in this example and it will be unrecoverable. 224 | 225 | ```bash 226 | # These deletes and purges take about 30 minutes to run. 227 | az group delete -n $RESOURCE_GROUP -y 228 | 229 | # Purge the soft delete resources 230 | az cognitiveservices account purge -g $RESOURCE_GROUP -l $LOCATION -n aif${BASE_NAME} 231 | ``` 232 | 233 | ## Contributions 234 | 235 | Please see our [Contributor guide](./CONTRIBUTING.md). 236 | 237 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact with any additional questions or comments. 238 | 239 | With :heart: from Azure Patterns & Practices, [Azure Architecture Center](https://azure.com/architecture). 240 | -------------------------------------------------------------------------------- /docs/media/basic-architecture.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | VBackground-1 204 | 206 | 207 | 实心 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | openai-end-to-end-basic 222 | 224 | 225 | Rectangle.2239 226 | 227 | 228 | 229 | 230 | 231 | 232 | Rectangle.1683 233 | 234 | 235 | 236 | 237 | 238 | 239 | Rectangle.1287 240 | 241 | 242 | 243 | 244 | 245 | 246 | Rectangle.1206 247 | 248 | 249 | 250 | 251 | 252 | 253 | Sheet.5 254 | 255 | Sheet.6 256 | 257 | Sheet.7 258 | 259 | Sheet.8 260 | 261 | 262 | 263 | Sheet.9 264 | 268 | 269 | 270 | 271 | 272 | Sheet.10 273 | User 274 | 275 | 276 | 277 | 278 | User 279 | 280 | 281 | Sheet.11 282 | 283 | 284 | 285 | Rectangle.416 286 | 287 | 288 | 289 | 290 | 291 | 292 | Sheet.13 293 | Monitoring 294 | 295 | 296 | 297 | 298 | Monitoring 299 | 300 | Icon-manage-310 301 | 302 | Sheet.15 303 | 305 | 306 | 307 | Sheet.16 308 | 311 | 312 | 313 | Sheet.17 314 | 321 | 322 | 323 | Sheet.18 324 | 325 | 326 | 327 | Sheet.19 328 | 329 | 330 | 331 | 332 | Icon-manage-317 333 | 334 | Sheet.21 335 | 336 | 337 | 338 | Sheet.22 339 | 340 | 341 | 342 | Sheet.23 343 | 345 | 346 | 347 | Sheet.24 348 | 350 | 351 | 352 | Sheet.25 353 | 355 | 356 | 357 | Sheet.26 358 | 360 | 361 | 362 | Sheet.27 363 | 365 | 366 | 367 | Sheet.28 368 | 370 | 371 | 372 | Sheet.29 373 | 374 | 375 | 376 | 377 | Sheet.30 378 | Application Insights 379 | 380 | 381 | 382 | 383 | Application Insights 385 | 386 | Sheet.31 387 | Azure Monitor 388 | 389 | 390 | 391 | 392 | Azure Monitor 394 | 395 | Icon-web-41.1007 396 | 397 | ee75dd06-1aca-4f76-9d11-d05a284 398 | 400 | 401 | 402 | Sheet.34 403 | 406 | 407 | 408 | Sheet.35 409 | 411 | 412 | 413 | Sheet.36 414 | 416 | 417 | 418 | Sheet.37 419 | 420 | 421 | 422 | Sheet.38 423 | 426 | 427 | 428 | Sheet.39 429 | 432 | 433 | 434 | Sheet.40 435 | 436 | 437 | 438 | Sheet.41 439 | 442 | 443 | 444 | Sheet.42 445 | 446 | 447 | 448 | Sheet.43 449 | 452 | 453 | 454 | Sheet.44 455 | 456 | 457 | 458 | Sheet.45 459 | 460 | 461 | 462 | 463 | Sheet.46 464 | App Service 465 | 466 | 467 | 468 | 469 | App Service 470 | 471 | Sheet.47 472 | Azure AI Search 473 | 474 | 475 | 476 | 477 | Azure AI Search 479 | 480 | Sheet.48 481 | 484 | 485 | 486 | Icon-web-41.1208 487 | 488 | ee75dd06-1aca-4f76-9d11-d05a284 489 | 491 | 492 | 493 | Sheet.51 494 | 497 | 498 | 499 | Sheet.52 500 | 502 | 503 | 504 | Sheet.53 505 | 507 | 508 | 509 | Sheet.54 510 | 511 | 512 | 513 | Sheet.55 514 | 517 | 518 | 519 | Sheet.56 520 | 523 | 524 | 525 | Sheet.57 526 | 527 | 528 | 529 | Sheet.58 530 | 533 | 534 | 535 | Sheet.59 536 | 537 | 538 | 539 | Sheet.60 540 | 543 | 544 | 545 | Sheet.61 546 | 547 | 548 | 549 | Sheet.62 550 | 551 | 552 | 553 | 554 | Sheet.63 555 | App Service instance 556 | 557 | 558 | 559 | 560 | App Service instance 562 | 563 | Icon-identity-227 564 | 565 | Sheet.65 566 | 567 | Sheet.66 568 | 570 | 571 | 572 | Sheet.67 573 | 574 | 575 | 576 | Sheet.68 577 | 578 | 579 | 580 | Sheet.69 581 | 582 | 583 | 584 | Sheet.70 585 | 586 | 587 | 588 | Sheet.71 589 | 590 | 591 | 592 | Sheet.72 593 | 594 | 595 | 596 | Sheet.73 597 | 598 | e189a61f-631a-4122-bb2b-079e860 599 | 608 | 609 | 610 | fb7033ee-4650-4886-80c7-eddf625 611 | 614 | 615 | 616 | b166b8c2-b9ee-4c3d-bf7a-77bd5ce 617 | 620 | 621 | 622 | baf437fe-3483-4a25-94ba-1e84a64 623 | 626 | 627 | 628 | 629 | 630 | 631 | Sheet.78 632 | Managed identity 633 | 634 | 635 | 636 | 637 | Managed identity 639 | 640 | Icon-web-44 641 | 642 | Sheet.80 643 | 647 | 648 | 649 | Sheet.81 650 | 657 | 658 | 659 | Sheet.82 660 | 661 | 662 | 663 | 664 | Rectangle.1614 665 | 666 | 667 | 668 | 669 | 670 | 671 | Sheet.84 672 | Azure OpenAI Model 673 | 674 | 675 | 676 | 677 | Azure OpenAI model 679 | 680 | Sheet.85 681 | App Service built-in authentication (Easy Auth) 682 | 683 | 684 | 685 | 686 | App Service built-in authentication (Easy Auth) 688 | 689 | Sheet.86 690 | 691 | Sheet.87 692 | 695 | 696 | 697 | Sheet.88 698 | 702 | 703 | 704 | Sheet.89 705 | 706 | 707 | 708 | 709 | Sheet.90 710 | 711 | 712 | 713 | Sheet.91 714 | 715 | 716 | 717 | Sheet.92 718 | https://domainname.azurewebsites.net 719 | 720 | 721 | 722 | 723 | https://domainname.azurewebsites.net 724 | 725 | Sheet.93 726 | 727 | Sheet.94 728 | 736 | 737 | 738 | 739 | Sheet.95 740 | 741 | Sheet.96 742 | 756 | 757 | 758 | 759 | Sheet.97 760 | 761 | Sheet.98 762 | 780 | 781 | 782 | 783 | Sheet.99 784 | 785 | Sheet.100 786 | 788 | 789 | 790 | Sheet.101 791 | 797 | 798 | 799 | 800 | Sheet.102 801 | 802 | Sheet.103 803 | 817 | 818 | 819 | Sheet.104 820 | 826 | 827 | 828 | 829 | Sheet.105 830 | 831 | Sheet.106 832 | 843 | 844 | 845 | 846 | Sheet.107 847 | Microsoft Foundry project 848 | 849 | 850 | 851 | 852 | Foundry project 853 | 854 | Sheet.108 855 | 856 | 957 | 958 | 959 | 960 | Circle.1742 961 | 962 | 963 | 964 | 965 | 966 | 967 | Rectangle.2032 968 | 969 | 970 | 971 | 972 | 973 | 974 | Sheet.111 975 | Azure AI Agent Service 976 | 977 | 978 | 979 | 980 | Foundry Agent Service 982 | 983 | Sheet.112 984 | 985 | 986 | 987 | Rectangle.1533 988 | 989 | 990 | 991 | 992 | 993 | 994 | Sheet.114 995 | Microsoft Foundry account 996 | 997 | 998 | 999 | 1000 | Microsoft Foundry account 1002 | 1003 | Sheet.115 1004 | 1005 | Sheet.116 1006 | 1008 | 1009 | 1010 | Sheet.117 1011 | 1013 | 1014 | 1015 | Sheet.118 1016 | 1019 | 1020 | 1021 | 1022 | Sheet.119 1023 | 1024 | 1025 | 1026 | Sheet.120 1027 | Microsoft Foundry 1028 | 1029 | 1030 | 1031 | 1032 | Microsoft Foundry 1033 | 1034 | Sheet.121 1035 | 1036 | Sheet.122 1037 | 1042 | 1043 | 1044 | 1045 | Sheet.123 1046 | 1047 | Icon-identity-227.1374 1048 | 1049 | Sheet.125 1050 | 1051 | Sheet.126 1052 | 1054 | 1055 | 1056 | Sheet.127 1057 | 1058 | 1059 | 1060 | Sheet.128 1061 | 1062 | 1063 | 1064 | Sheet.129 1065 | 1066 | 1067 | 1068 | Sheet.130 1069 | 1070 | 1071 | 1072 | Sheet.131 1073 | 1074 | 1075 | 1076 | Sheet.132 1077 | 1078 | 1079 | 1080 | Sheet.133 1081 | 1082 | e189a61f-631a-4122-bb2b-079e860 1083 | 1092 | 1093 | 1094 | fb7033ee-4650-4886-80c7-eddf625 1095 | 1098 | 1099 | 1100 | b166b8c2-b9ee-4c3d-bf7a-77bd5ce 1101 | 1104 | 1105 | 1106 | baf437fe-3483-4a25-94ba-1e84a64 1107 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | Sheet.138 1116 | Managed identities 1117 | 1118 | 1119 | 1120 | 1121 | Managed identities 1123 | 1124 | 1125 | 1126 | --------------------------------------------------------------------------------