Skip to content

Commit 4383826

Browse files
authored
Merge branch 'microsoft-foundry:main' into main
2 parents 97bb6b4 + 216eea2 commit 4383826

File tree

6 files changed

+73
-20
lines changed

6 files changed

+73
-20
lines changed

infrastructure/infrastructure-setup-bicep/15-private-network-standard-agent-setup/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ To use an existing VNet and subnets, set the existingVnetResourceId parameter to
117117
- param agentSubnetPrefix string = '192.168.0.0/24' //optional, default is '192.168.0.0/24'
118118
- param peSubnetName string = 'pe-subnet' //optional, default is 'pe-subnet'
119119
- param peSubnetPrefix string = '192.168.1.0/24' //optional, default is '192.168.1.0/24'
120+
- param dnsZonesSubscriptionId string = '' //optional, leave empty to use current subscription, or set to a subscription ID if DNS zones are in a different subscription
120121
- param existingDnsZones = {
121122

122123
'privatelink.services.ai.azure.com': 'privzoneRG' //add resource group name where your private DNS zone is located
@@ -125,6 +126,10 @@ To use an existing VNet and subnets, set the existingVnetResourceId parameter to
125126

126127
💡 If subnets information is provided then make sure it exist within the specified VNet to avoid deployment errors. If subnet information is not provided, the template will create subnets with the default address space.
127128

129+
💡 **Cross-Subscription DNS Zones**: All DNS zones specified in `existingDnsZones` will be referenced from the subscription specified in `dnsZonesSubscriptionId`. Leave this parameter empty (default) to use the current deployment subscription, or set it to a subscription ID if your DNS zones are located in a different subscription.
130+
131+
⚠️ **Important**: When `dnsZonesSubscriptionId` is set to a different subscription, ALL DNS zones in `existingDnsZones` must have resource groups specified (non-empty values). The template does not support creating new DNS zones in a different subscription. Empty resource groups are only allowed when creating zones in the current deployment subscription.
132+
128133

129134
2. **Use an existing Azure Cosmos DB for NoSQL**
130135

infrastructure/infrastructure-setup-bicep/15-private-network-standard-agent-setup/main.bicep

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ param azureCosmosDBAccountResourceId string = ''
9595
//@description('Optional: Resource group containing existing private DNS zones. If specified, DNS zones will not be created.')
9696
//param existingDnsZonesResourceGroup string = ''
9797

98+
@description('Subscription ID where existing private DNS zones are located. Leave empty to use current subscription.')
99+
param dnsZonesSubscriptionId string = ''
100+
98101
@description('Object mapping DNS zone names to their resource group, or empty string to indicate creation')
99102
param existingDnsZones object = {
100103
'privatelink.services.ai.azure.com': ''
@@ -146,6 +149,9 @@ var vnetResourceGroupName = existingVnetPassedIn ? vnetParts[4] : resourceGroup(
146149
var existingVnetName = existingVnetPassedIn ? last(vnetParts) : vnetName
147150
var trimVnetName = trim(existingVnetName)
148151

152+
// Resolve DNS zones subscription ID - use current subscription if not specified
153+
var resolvedDnsZonesSubscriptionId = empty(dnsZonesSubscriptionId) ? subscription().subscriptionId : dnsZonesSubscriptionId
154+
149155
@description('The name of the project capability host to be created')
150156
param projectCapHost string = 'caphostproj'
151157

@@ -196,6 +202,7 @@ module validateExistingResources 'modules-network-secured/validate-existing-reso
196202
azureCosmosDBAccountResourceId: azureCosmosDBAccountResourceId
197203
existingDnsZones: existingDnsZones
198204
dnsZoneNames: dnsZoneNames
205+
dnsZonesSubscriptionId: resolvedDnsZonesSubscriptionId
199206
}
200207
}
201208

@@ -264,6 +271,7 @@ module privateEndpointAndDNS 'modules-network-secured/private-endpoint-and-dns.b
264271
storageAccountResourceGroupName: azureStorageResourceGroupName // Resource Group for Storage Account
265272
storageAccountSubscriptionId: azureStorageSubscriptionId // Subscription ID for Storage Account
266273
existingDnsZones: existingDnsZones
274+
dnsZonesSubscriptionId: resolvedDnsZonesSubscriptionId
267275
}
268276
dependsOn: [
269277
aiSearch // Ensure AI Search exists

infrastructure/infrastructure-setup-bicep/15-private-network-standard-agent-setup/main.bicepparam

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
using './main.bicep'
22

3-
param location = 'eastus2'
4-
param aiServices = 'aiservices'
5-
param modelName = 'gpt-4o'
3+
param location = 'westus'
4+
param aiServices = 'foundry'
5+
param modelName = 'gpt-4.1'
66
param modelFormat = 'OpenAI'
7-
param modelVersion = '2024-11-20'
7+
param modelVersion = '2025-04-14'
88
param modelSkuName = 'GlobalStandard'
99
param modelCapacity = 30
1010
param firstProjectName = 'project'
@@ -20,8 +20,13 @@ param agentSubnetName = 'agent-subnet'
2020
param aiSearchResourceId = ''
2121
param azureStorageAccountResourceId = ''
2222
param azureCosmosDBAccountResourceId = ''
23-
// Pass the DNS zone map here
24-
// Leave empty to create new DNS zone, add the resource group of existing DNS zone to use it
23+
24+
// Subscription ID where DNS zones are located (leave empty to use deployment subscription)
25+
// ⚠️ If set to a different subscription, ALL zones below MUST have resource groups specified
26+
param dnsZonesSubscriptionId = ''
27+
28+
// DNS zone map: provide resource group name to use existing zone, or leave empty to create new
29+
// Note: Empty values only allowed when dnsZonesSubscriptionId is empty or matches current subscription
2530
param existingDnsZones = {
2631
'privatelink.services.ai.azure.com': ''
2732
'privatelink.openai.azure.com': ''

infrastructure/infrastructure-setup-bicep/15-private-network-standard-agent-setup/modules-network-secured/private-endpoint-and-dns.bicep

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ param existingDnsZones object = {
7272
'privatelink.documents.azure.com': ''
7373
}
7474

75+
@description('Subscription ID where existing private DNS zones are located. Should be resolved to current subscription if empty.')
76+
param dnsZonesSubscriptionId string
77+
7578
// ---- Resource references ----
7679
resource aiAccount 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = {
7780
name: aiAccountName
@@ -221,7 +224,7 @@ resource aiServicesPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01'
221224
// Reference existing private DNS zone if provided
222225
resource existingAiServicesPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = if (!empty(aiServicesDnsZoneRG)) {
223226
name: aiServicesDnsZoneName
224-
scope: resourceGroup(aiServicesDnsZoneRG)
227+
scope: resourceGroup(dnsZonesSubscriptionId, aiServicesDnsZoneRG)
225228
}
226229
//creating condition if user pass existing dns zones or not
227230
var aiServicesDnsZoneId = empty(aiServicesDnsZoneRG) ? aiServicesPrivateDnsZone.id : existingAiServicesPrivateDnsZone.id
@@ -234,7 +237,7 @@ resource openAiPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = i
234237
// Reference existing private DNS zone if provided
235238
resource existingOpenAiPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = if (!empty(openAiDnsZoneRG)) {
236239
name: openAiDnsZoneName
237-
scope: resourceGroup(openAiDnsZoneRG)
240+
scope: resourceGroup(dnsZonesSubscriptionId, openAiDnsZoneRG)
238241
}
239242
//creating condition if user pass existing dns zones or not
240243
var openAiDnsZoneId = empty(openAiDnsZoneRG) ? openAiPrivateDnsZone.id : existingOpenAiPrivateDnsZone.id
@@ -247,7 +250,7 @@ resource cognitiveServicesPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020
247250
// Reference existing private DNS zone if provided
248251
resource existingCognitiveServicesPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = if (!empty(cognitiveServicesDnsZoneRG)) {
249252
name: cognitiveServicesDnsZoneName
250-
scope: resourceGroup(cognitiveServicesDnsZoneRG)
253+
scope: resourceGroup(dnsZonesSubscriptionId, cognitiveServicesDnsZoneRG)
251254
}
252255
//creating condition if user pass existing dns zones or not
253256
var cognitiveServicesDnsZoneId = empty(cognitiveServicesDnsZoneRG) ? cognitiveServicesPrivateDnsZone.id : existingCognitiveServicesPrivateDnsZone.id
@@ -260,7 +263,7 @@ resource aiSearchPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' =
260263
// Reference existing private DNS zone if provided
261264
resource existingAiSearchPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = if (!empty(aiSearchDnsZoneRG)) {
262265
name: aiSearchDnsZoneName
263-
scope: resourceGroup(aiSearchDnsZoneRG)
266+
scope: resourceGroup(dnsZonesSubscriptionId, aiSearchDnsZoneRG)
264267
}
265268
//creating condition if user pass existing dns zones or not
266269
var aiSearchDnsZoneId = empty(aiSearchDnsZoneRG) ? aiSearchPrivateDnsZone.id : existingAiSearchPrivateDnsZone.id
@@ -273,7 +276,7 @@ resource storagePrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' =
273276
// Reference existing private DNS zone if provided
274277
resource existingStoragePrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = if (!empty(storageDnsZoneRG)) {
275278
name: storageDnsZoneName
276-
scope: resourceGroup(storageDnsZoneRG)
279+
scope: resourceGroup(dnsZonesSubscriptionId, storageDnsZoneRG)
277280
}
278281
//creating condition if user pass existing dns zones or not
279282
var storageDnsZoneId = empty(storageDnsZoneRG) ? storagePrivateDnsZone.id : existingStoragePrivateDnsZone.id
@@ -286,7 +289,7 @@ resource cosmosDBPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' =
286289
// Reference existing private DNS zone if provided
287290
resource existingCosmosDBPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' existing = if (!empty(cosmosDBDnsZoneRG)) {
288291
name: cosmosDBDnsZoneName
289-
scope: resourceGroup(cosmosDBDnsZoneRG)
292+
scope: resourceGroup(dnsZonesSubscriptionId, cosmosDBDnsZoneRG)
290293
}
291294
//creating condition if user pass existing dns zones or not
292295
var cosmosDBDnsZoneId = empty(cosmosDBDnsZoneRG) ? cosmosDBPrivateDnsZone.id : existingCosmosDBPrivateDnsZone.id

infrastructure/infrastructure-setup-bicep/15-private-network-standard-agent-setup/modules-network-secured/validate-existing-resources.bicep

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ output azureStorageResourceGroupName string = azureStorageResourceGroupName
6464
@description('Object mapping DNS zone names to their resource group, or empty string to indicate creation')
6565
param existingDnsZones object
6666

67+
@description('Subscription ID where existing private DNS zones are located. Should be resolved to current subscription if empty.')
68+
param dnsZonesSubscriptionId string
69+
6770
@description('List of private DNS zone names to validate')
6871
param dnsZoneNames array
6972

samples/typescript/quickstart/src/quickstart-chat-with-agent.ts

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,45 @@ const deploymentName = process.env["MODEL_DEPLOYMENT_NAME"] || "<model deploymen
88
async function main(): Promise<void> {
99
const project = new AIProjectClient(projectEndpoint, new DefaultAzureCredential());
1010
const openAIClient = await project.getOpenAIClient();
11-
const response = await openAIClient.responses.create({
11+
12+
// Create agent
13+
console.log("Creating agent...");
14+
const agent = await project.agents.createVersion("my-agent-basic", {
15+
kind: "prompt",
1216
model: deploymentName,
13-
input: "What is the size of France in square miles?",
17+
instructions: "You are a helpful assistant that answers general questions",
1418
});
15-
const response2 = await openAIClient.responses.create({
16-
model: deploymentName,
17-
input: "And what is the capital city?",
18-
previous_response_id: response.id,
19+
console.log(`Agent created (id: ${agent.id}, name: ${agent.name}, version: ${agent.version})`);
20+
21+
// Create conversation with initial user message
22+
// You can save the conversation ID to database to retrieve later
23+
console.log("\nCreating conversation with initial user message...");
24+
const conversation = await openAIClient.conversations.create({
25+
items: [
26+
{ type: "message", role: "user", content: "What is the size of France in square miles?" },
27+
],
1928
});
20-
console.log(`Response output: ${response2.output_text}`);
21-
};
29+
console.log(`Created conversation with initial user message (id: ${conversation.id})`);
30+
31+
// Generate response using the agent
32+
console.log("\nGenerating response...");
33+
const response = await openAIClient.responses.create(
34+
{
35+
conversation: conversation.id,
36+
},
37+
{
38+
body: { agent: { name: agent.name, type: "agent_reference" } },
39+
},
40+
);
41+
console.log(`Response output: ${response.output_text}`);
42+
43+
// Clean up
44+
console.log("\nCleaning up resources...");
45+
await openAIClient.conversations.delete(conversation.id);
46+
console.log("Conversation deleted");
47+
48+
await project.agents.deleteVersion(agent.name, agent.version);
49+
console.log("Agent deleted");
50+
}
2251

2352
main().catch(console.error);

0 commit comments

Comments
 (0)