Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions samples/python/foundry-ai-teammate/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#azd
.azure/

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/

# ASP.NET Scaffolding
ScaffoldingReadMe.txt

# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg

# Others
~$*
*~
CodeCoverage/

# MSBuild Binary and Structured Log
*.binlog

# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*

# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
20 changes: 20 additions & 0 deletions samples/python/foundry-ai-teammate/azure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: foundry-a365

hooks:
postprovision:
shell: pwsh
run: ./scripts/post-provision.ps1
interactive: true
continueOnError: false

# services:
# web:
# project: ./src
# language: csharp
# host: foundry.containeragent
# hooks:
# # This hook runs before this specific service is built
# prebuild:
# posix:
# shell: sh
# run: ./service-prebuild.sh
Binary file added samples/python/foundry-ai-teammate/image-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added samples/python/foundry-ai-teammate/image-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added samples/python/foundry-ai-teammate/image-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added samples/python/foundry-ai-teammate/image-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added samples/python/foundry-ai-teammate/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
153 changes: 153 additions & 0 deletions samples/python/foundry-ai-teammate/infra/main.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
targetScope = 'resourceGroup'

// =================================================================================================
// Main parameters
// =================================================================================================

@minLength(1)
@maxLength(64)
@description('Name of the application. Used to ensure resource names are unique.')
param environmentName string

@minLength(1)
@description('Primary location for all resources')
param location string

// =================================================================================================
// Project module parameters
// =================================================================================================

@description('Name of the Cognitive Services account')
param accountName string = '${environmentName}acct'

@description('Name of the Cognitive Services project')
param projectName string = '${environmentName}proj'

@description('Name of the Container Registry')
param containerRegistryName string = '${environmentName}acr'

@description('SKU of Cognitive Services account')
param cognitiveServicesSku string = 'S0'

@description('SKU of Container Registry')
@allowed(['Basic', 'Standard', 'Premium'])
param containerRegistrySku string = 'Basic'

param agentName string = 'foundry-agent'

param maibName string = '${agentName}-maib'

// =================================================================================================
// Bot Service module parameters
// =================================================================================================

@description('Name of the Bot Service')
param botName string = '${agentName}-bot'

@description('Display name of the bot')
param botDisplayName string = '${agentName} Bot'

@description('SKU of the Bot Service')
param botServiceSku string = 'F0'

@description('Model name')
param modelName string = 'gpt-5.3-chat'

@description('Model version')
param modelVersion string = '2026-03-03'

// =================================================================================================
// Common parameters
// =================================================================================================

@description('Tags to apply to all resources')
param tags object = {}

// =================================================================================================
// Module deployments
// =================================================================================================

// 1. Deploy the project module (Cognitive Services account, project, and Container Registry)
module project 'modules/project.bicep' = {
name: 'project-deployment'
params: {
accountName: accountName
projectName: projectName
containerRegistryName: containerRegistryName
location: location
tags: tags
cognitiveServicesSku: cognitiveServicesSku
containerRegistrySku: containerRegistrySku
modelName: modelName
modelVersion: modelVersion
}
}

// 2. Create deployment script UMI and grant roles on RG.
module deploymentScriptUmi 'modules/deployment-script-umi.bicep' = {
name: 'deployment-script-umi'
dependsOn: [
project
]
}

// 3. Create managed agent identity blueprint using a deployment script as that is a dataplane operation.
module deploymentScriptAgent 'modules/maib-creation-script.bicep' = {
name: 'maib-creation-script'
params: {
uamiResourceId: deploymentScriptUmi.outputs.uamiResourceId
azureAIProjectEndpoint: project.outputs.foundryProjectEndpoint
maibName: maibName
}
dependsOn: [
deploymentScriptUmi
]
}


// 4. Deploy the bot service module
module botService 'modules/botservice.bicep' = {
name: 'botservice-deployment'
params: {
botName: botName
displayName: botDisplayName
msaAppId: deploymentScriptAgent.outputs.blueprintClientId
endpoint: 'https://${accountName}.services.ai.azure.com/api/projects/${projectName}/agents/${agentName}/endpoint/protocols/activityProtocol?api-version=2025-05-15-preview'
botServiceSku: botServiceSku
}
dependsOn: [
deploymentScriptAgent
]
}

// =================================================================================================
// Outputs - These become environment variables in post-provision.sh
// =================================================================================================

@description('ACR login server endpoint')
output AZURE_CONTAINER_REGISTRY_ENDPOINT string = project.outputs.acrloginServer

output AZURE_AI_PROJECT_ENDPOINT string = project.outputs.foundryProjectEndpoint

@description('Agent identity blueprint ID')
output AGENT_IDENTITY_BLUEPRINT_ID string = deploymentScriptAgent.outputs.blueprintClientId

output SUBSCRIPTION_ID string = subscription().subscriptionId

output RESOURCE_GROUP string = resourceGroup().name

output LOCATION string = location

output ACCOUNT_NAME string = accountName

output PROJECT_NAME string = projectName

output AGENT_NAME string = agentName

output TENANT_ID string = tenant().tenantId

output PROJECT_PRINCIPAL_ID string = project.outputs.foundryProjectPrincipalId

output MAIB_NAME string = maibName

output MODEL_NAME string = modelName
33 changes: 33 additions & 0 deletions samples/python/foundry-ai-teammate/infra/modules/botservice.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
param botName string
param displayName string
param msaAppId string
param endpoint string
param botServiceSku string = 'F0'

// Bot Service resource
resource botService 'Microsoft.BotService/botServices@2022-09-15' = {
name: botName
kind: 'azurebot'
location: 'global'
sku: {
name: botServiceSku
}
properties: {
displayName: displayName
endpoint: endpoint
msaAppId: msaAppId
msaAppTenantId: tenant().tenantId
msaAppType: 'SingleTenant'
}
}

// Connect the bot service to Microsoft Teams
resource botServiceMsTeamsChannel 'Microsoft.BotService/botServices/channels@2021-03-01' = {
parent: botService
location: 'global'
name: 'MsTeamsChannel'
properties: {
channelName: 'MsTeamsChannel'
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
targetScope = 'resourceGroup'

@description('Name of the User Assigned Managed Identity to create')
param identityName string = 'foundry-deployment-script-umi'

//
// 1. Create the user-assigned identity
//
resource umi 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: identityName
location: resourceGroup().location
}

//
// 2. Grant Contributor role on this resource group
//
resource contributorAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, umi.id, 'Contributor')
scope: resourceGroup()
properties: {
roleDefinitionId: subscriptionResourceId(
'Microsoft.Authorization/roleDefinitions',
'b24988ac-6180-42a0-ab88-20f7382dd24c' // Contributor Role ID
)
principalId: umi.properties.principalId
principalType: 'ServicePrincipal'
}
}

var cognitiveServicesUserRoleDefinitionId = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908')

// Role assignment: Grant AcrPull role to the project's system managed identity
resource cogServicesUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(resourceGroup().id, umi.id, cognitiveServicesUserRoleDefinitionId)
scope: resourceGroup()
properties: {
roleDefinitionId: cognitiveServicesUserRoleDefinitionId
principalId: umi.properties.principalId
principalType: 'ServicePrincipal'
}
}


//
// Optional: Output the identity info
//
output uamiClientId string = umi.properties.clientId
output uamiPrincipalId string = umi.properties.principalId
output uamiResourceId string = umi.id
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
@description('User-assigned managed identity resource ID that the script will run as')
param uamiResourceId string

@description('Azure AI Project Endpoint URL')
param azureAIProjectEndpoint string

@description('Managed agent identity blueprint name for the Azure AI Project')
param maibName string

// PowerShell deployment script
resource psScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
name: 'create-agent-script'
location: resourceGroup().location
kind: 'AzurePowerShell'
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${uamiResourceId}': {}
}
}
properties: {
// Check supported versions for your region if this fails
azPowerShellVersion: '11.5'
timeout: 'PT15M'
retentionInterval: 'P1D'

arguments: '-AzureAIProjectEndpoint "${azureAIProjectEndpoint}" -MAIBName "${maibName}"'

environmentVariables: [
{
name: 'RESOURCE_GROUP_NAME'
value: resourceGroup().name
}
]

scriptContent: '''
param(
[Parameter(Mandatory = $true)]
[string] $AzureAIProjectEndpoint,
[Parameter(Mandatory = $true)]
[string] $MAIBName
)

$ErrorActionPreference = "Stop"

$maibUrl = "$($AzureAIProjectEndpoint)/managedagentidentityblueprints/$($MAIBName)?api-version=2025-11-15-preview"

Write-Host "Connecting with managed identity..."
Connect-AzAccount -Identity

Write-Host "Getting access token for https://ai.azure.com ..."
$tokenResponse = Get-AzAccessToken -ResourceUrl "https://ai.azure.com"
$aiAzureToken = $tokenResponse.Token | ConvertFrom-SecureString -AsPlainText
Write-Host "Token length: $($aiAzureToken.Length)"

$headers = @{
"Content-Type" = "application/json"
"Accept" = "application/json"
"Authorization" = "Bearer $aiAzureToken"
}

Write-Host "Creating managed agent identity blueprint at: $maibUrl"

$response = Invoke-RestMethod -Uri $maibUrl `
-Method Put `
-Headers $headers `
-ErrorAction Stop

Write-Host ""
Write-Host "Response:"
$response | ConvertTo-Json -Depth 100 | Write-Host

$blueprintClientId = $response.agentIdentityBlueprint.clientId

$DeploymentScriptOutputs = @{
blueprintClientId = $blueprintClientId
}

'''

}
}

output blueprintClientId string = psScript.properties.outputs.blueprintClientId
Loading
Loading