Skip to content

Commit 4304ef8

Browse files
committed
Merge branch 'release-build-agents' of https://github.com/MicrosoftDocs/azure-ai-docs-pr into amandabuild-4
2 parents 6978a45 + f098560 commit 4304ef8

36 files changed

+1238
-1044
lines changed

.openpublishing.redirection.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
},
9393
{
9494
"source_path_from_root": "/articles/ai-services/agents/how-to/tools/licensed-data.md",
95-
"redirect_url": "/azure/ai-services/agents/how-to/tools/catalog",
95+
"redirect_url": "/azure/ai-services/agents/how-to/tools/overview",
9696
"redirect_document_id": false
9797
},
9898
{
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
title: Built-in enterprise readiness with standard agent setup
3+
titleSuffix: Azure AI Foundry
4+
description: Learn about the enterprise features of the standard setup
5+
manager: nitinme
6+
author: fosteramanda
7+
ms.author: fosteramanda
8+
ms.service: azure-ai-agent-service
9+
ms.topic: conceptual
10+
ms.date: 05/05/2025
11+
ms.custom: azure-ai-agents
12+
---
13+
14+
# Built-in enterprise readiness with standard agent setup
15+
16+
Standard Agent Setup offers enterprise-grade security, compliance, and control. This configuration uses customer-managed, single-tenant resources to store agent state and ensures all data remains within your control.
17+
18+
In this setup:
19+
* Agent states (files, threads, vector stores) are stored in your own Azure resources.
20+
* Available with both public networking and private networking (Bring Your Own virtual network) options.
21+
22+
## Leveraging your own resources for storing customer data
23+
Both standard setup configurations are designed to give you complete control over sensitive data by requiring the use of your own Azure resources. The required Bring Your Own (BYO) resources include:
24+
* BYO File Storage: All files uploaded by developers (during agent configuration) or end-users (during interactions) are stored directly in the customer’s Azure Storage account.
25+
* BYO Search: All vector stores created by the agent leverage the customer’s Azure AI Search resource.
26+
* BYO Thread Storage: All customer messages and conversation history will be stored in the customer’s own Azure Cosmos DB account.
27+
28+
By bundling these BYO features (file storage, search, and thread storage), the standard setup guarantees that your deployment is secure by default. All data processed by Azure AI Agent Service is automatically stored at rest in your own Azure resources, helping you meet internal policies, compliance requirements, and enterprise security standards.
29+
30+
## Project-Level Data Isolation
31+
32+
Azure AI Foundry enforces project-level data isolation by default. When you configure your own resources in the project capability host:
33+
* **Azure Storage**: Two Blob containers are automatically provisioned:
34+
* One for uploaded files
35+
* One for intermediate system data (for example, chunks, embeddings)
36+
* **Azure Cosmos DB**: Three containers are provisioned under a dedicated enterprise_memory database:
37+
* thread-message-store: End-user conversations
38+
* system-thread-message-store: Internal system messages
39+
* agent-entity-store: Model inputs and outputs
40+
41+
This default behavior was chosen to reduce configuration complexity while still enforcing strict data boundaries—ensuring each project has a clean, isolated storage footprint without requiring manual setup.
42+
43+
## Capability hosts
44+
**Capability hosts** are sub-resources on both the Account and Project, enabling interaction with the Azure AI Agent Service.
45+
- **Account Capability Host**: The account capability host has an empty request body except for the parameter capabilityHostKind="Agents".
46+
- **Project Capability Host**: Specifies resources for storing agent state, either managed multitenant (basic setup) or customer-owned (standard setup), single-tenant resource. Think of project capability host as the project settings.
47+
48+
### Limitations
49+
- **Update Not Supported**: Cannot update the capability host for a project or account.
50+
51+
52+
## Step by Step Provisioning Process
53+
1. Create project dependent resources for standard setup
54+
* Create new (or pass in resource ID of existing) Cosmos DB resource
55+
* Create new (or pass in resource ID of existing) Azure Storage resource
56+
* Create new (or pass in resource ID of existing) Azure AI Search resource
57+
* Create a new Key Vault resource
58+
* [Optional]: Create new application insights resource
59+
* [Optional]: pass in resource ID of existing AI Foundry resource
60+
2. Create Azure AI Foundry Resource (cognitive service/accounts kind=AIServices)
61+
3. Create Account-level connections
62+
* Create account connection to Application Insights resource
63+
4. Deploy gpt-4o or other agent compatible model
64+
5. Create Project (cognitive service/accounts/project)
65+
6. Create project connections
66+
* [if provided] Project connection to AI Foundry resource
67+
* Create project connection to Azure Storage account
68+
* Create project connection to Azure AI Search account
69+
* Create project connection to Cosmos DB account
70+
7. Assign the project-managed identity (including for SMI) the following roles:
71+
* Cosmos DB Operator at the scope of the account level for the Cosmos DB account resource
72+
* Storage Account Contributor at the scope of the account level for the Storage Account resource
73+
8. Set Account capability host with empty properties section.
74+
9. Set Project capability host with properties Cosmos DB, Azure Storage, AI Search connections
75+
10. Assign the Project Managed Identity (both for SMI and UMI) the following roles on the specified resource scopes:
76+
* Azure AI Search (can be assigned either before or after capHost creation)
77+
* Assign roles: Search Index Data Contributor, Search Service Contributor
78+
* Azure Blob Storage Container: `<workspaceId>-azureml-blobstore`
79+
* Assign role: Storage Blob Data Contributor
80+
* Azure Blob Storage Container: `<workspaceId>- agents-blobstore`
81+
* Assign role: Storage Blob Data Owner
82+
* Cosmos DB for NoSQL container: `<'${projectWorkspaceId}>-thread-message-store'`
83+
* Assign role: Cosmos DB Built-in Data Contributor
84+
* Cosmos DB for NoSQL container: `<'${projectWorkspaceId}>-thread-message-store'`
85+
* Assign role: Cosmos DB Built-in Data Contributor
86+
* Cosmos DB for NoSQL container: `<'${projectWorkspaceId}>-agent-entity-store'`
87+
* Assign role: Cosmos DB Built-in Data Contributor
88+
11. Once all resources are provisioned, all developers who want to create/edit agents in the project should be assigned the role: Azure AI User on the project scope.

articles/ai-services/agents/how-to/tools/azure-ai-search-samples.md

Lines changed: 98 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -136,112 +136,132 @@ print("Deleted agent")
136136

137137
:::zone pivot="csharp"
138138

139-
## Step 1: Create an Azure AI Client
140-
First, create an Azure AI Client using the connection string of your project.
139+
## Step 1: Create a project client
140+
Create a client object, which will contain the project endpoint for connecting to your AI project and other resources.
141141

142142
```csharp
143+
using Azure;
144+
using Azure.AI.Agents.Persistent;
145+
using Azure.Identity;
146+
using Microsoft.Extensions.Configuration;
143147
using System;
144-
using System.Threading.Tasks;
145-
using Azure.Core;
146-
using Azure.Core.TestFramework;
147-
using NUnit.Framework;
148-
using System.Collections.Generic;
149-
150-
// Create an Azure AI Client from a connection string, copied from your Azure AI Foundry project.
151-
// At the moment, it should be in the format "<HostName>;<AzureSubscriptionId>;<ResourceGroup>;<ProjectName>"
152-
// Customer needs to login to Azure subscription via Azure CLI and set the environment variables
153-
var connectionString = TestEnvironment.AzureAICONNECTIONSTRING;
154-
var clientOptions = new AIProjectClientOptions();
155-
156-
// Adding the custom headers policy
157-
clientOptions.AddPolicy(new CustomHeadersPolicy(), HttpPipelinePosition.PerCall);
158-
var projectClient = new AIProjectClient(connectionString, new DefaultAzureCredential(), clientOptions);
159-
```
148+
using System.Threading;
160149

161-
## Step 2: Get the connection ID for the Azure AI Search resource
162-
Get the connection ID of the Azure AI Search connection in the project.
150+
// Get Connection information from app configuration
151+
IConfigurationRoot configuration = new ConfigurationBuilder()
152+
.SetBasePath(AppContext.BaseDirectory)
153+
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
154+
.Build();
163155

164-
```csharp
165-
ListConnectionsResponse connections = await projectClient.GetConnectionsClient().GetConnectionsAsync(ConnectionType.AzureAISearch).ConfigureAwait(false);
156+
var projectEndpoint = configuration["ProjectEndpoint"];
157+
var modelDeploymentName = configuration["ModelDeploymentName"];
158+
var azureAiSearchConnectionId = configuration["AzureAiSearchConnectionId"];
166159

167-
if (connections?.Value == null || connections.Value.Count == 0)
168-
{
169-
throw new InvalidOperationException("No connections found for the Azure AI Search.");
170-
}
160+
// Create the Agent Client
161+
PersistentAgentsClient agentClient = new(projectEndpoint, new DefaultAzureCredential());
171162
```
172163

173-
## Step 3: Configure the Azure AI Search tool
174-
Using the connection ID you got in the previous step, you can now configure the Azure AI Search tool to use your Azure AI Search index.
164+
## Step 2: Configure the Azure AI Search tool
165+
Using the AI Search Connection ID, configure the Azure AI Search tool to use your Azure AI Search index.
175166

176167
```csharp
177-
// TO DO: replace this value with the connection ID of the search index
178-
ConnectionResponse connection = connections.Value[0];
168+
AzureAISearchResource searchResource = new(
169+
indexConnectionId: azureAiSearchConnectionId,
170+
indexName: "sample_index",
171+
topK: 5,
172+
filter: "category eq 'sleeping bag'",
173+
queryType: AzureAISearchQueryType.Simple
174+
);
175+
176+
ToolResources toolResource = new() { AzureAISearch = searchResource };
179177

180-
// Initialize agent Azure AI search tool and add the search index connection ID and index name
181-
// TO DO: replace <your-index-name> with the name of the index you want to use
182-
ToolResources searchResource = new ToolResources
183-
{
184-
AzureAISearch = new AzureAISearchResource
185-
{
186-
IndexList = { new IndexResource(connection.Id, "<your-index-name>", "<select-search-type>") }
187-
}
188-
};
189178
```
190179

191-
## Step 4: Create an agent with the Azure AI Search tool enabled
180+
## Step 3: Create an agent with the Azure AI Search tool enabled
192181
Change the model to the one deployed in your project. You can find the model name in the Azure AI Foundry under the **Models** tab. You can also change the name and instructions of the agent to suit your needs.
193182

194183
```csharp
195-
AgentsClient agentClient = projectClient.GetAgentsClient();
196-
197-
Response<Agent> agentResponse = await agentClient.CreateAgentAsync(
198-
model: "gpt-4o-mini",
199-
name: "my-assistant",
200-
instructions: "You are a helpful assistant.",
201-
tools: new List<ToolDefinition> { new AzureAISearchToolDefinition() },
202-
toolResources: searchResource);
203-
Agent agent = agentResponse.Value;
184+
// Create an agent with Tools and Tool Resources
185+
PersistentAgent agent = agentClient.Administration.CreateAgent(
186+
model: modelDeploymentName,
187+
name: "my-agent",
188+
instructions: "You are a helpful agent.",
189+
tools: [new AzureAISearchToolDefinition()],
190+
toolResources: toolResource);
191+
204192
```
205193

206-
## Step 5: Ask the agent questions about data in the index
194+
## Step 4: Ask the agent questions about data in the index
207195
Now that the agent is created, ask it questions about the data in your Azure AI Search index.
208196

209197
```csharp
210198
// Create thread for communication
211-
Response<AgentThread> threadResponse = await agentClient.CreateThreadAsync();
212-
AgentThread thread = threadResponse.Value;
199+
PersistentAgentThread thread = agentClient.Threads.CreateThread();
213200

214-
// Create message to thread
215-
Response<ThreadMessage> messageResponse = await agentClient.CreateMessageAsync(
201+
// Create message and run the agent
202+
ThreadMessage message = agentClient.Messages.CreateMessage(
216203
thread.Id,
217204
MessageRole.User,
218-
"what are my health insurance plan coverage types?");
219-
ThreadMessage message = messageResponse.Value;
205+
"What is the temperature rating of the cozynights sleeping bag?");
206+
ThreadRun run = agentClient.Runs.CreateRun(thread, agent);
207+
208+
```
209+
210+
## Step 4: Wait for the agent to complete and print the output
220211

221-
// Run the agent
222-
Response<ThreadRun> runResponse = await agentClient.CreateRunAsync(thread, agent);
212+
Wait for the agent to complete the run and print output to console.
223213

214+
```csharp
215+
// Wait for the agent to finish running
224216
do
225217
{
226-
await Task.Delay(TimeSpan.FromMilliseconds(500));
227-
runResponse = await agentClient.GetRunAsync(thread.Id, runResponse.Value.Id);
218+
Thread.Sleep(TimeSpan.FromMilliseconds(500));
219+
run = agentClient.Runs.GetRun(thread.Id, run.Id);
228220
}
229-
while (runResponse.Value.Status == RunStatus.Queued
230-
|| runResponse.Value.Status == RunStatus.InProgress);
221+
while (run.Status == RunStatus.Queued
222+
|| run.Status == RunStatus.InProgress);
231223

232-
Response<PageableList<ThreadMessage>> afterRunMessagesResponse
233-
= await agentClient.GetMessagesAsync(thread.Id);
234-
IReadOnlyList<ThreadMessage> messages = afterRunMessagesResponse.Value.Data;
224+
// Confirm that the run completed successfully
225+
if (run.Status != RunStatus.Completed)
226+
{
227+
throw new Exception("Run did not complete successfully, error: " + run.LastError?.Message);
228+
}
229+
230+
// Retrieve the messages from the agent client
231+
Pageable<ThreadMessage> messages = agentClient.Messages.GetMessages(
232+
threadId: thread.Id,
233+
order: ListSortOrder.Ascending
234+
);
235235

236-
// Note: messages iterate from newest to oldest, with the messages[0] being the most recent
236+
// Process messages in order
237237
foreach (ThreadMessage threadMessage in messages)
238238
{
239239
Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: ");
240240
foreach (MessageContent contentItem in threadMessage.ContentItems)
241241
{
242242
if (contentItem is MessageTextContent textItem)
243243
{
244-
Console.Write(textItem.Text);
244+
// We need to annotate only Agent messages.
245+
if (threadMessage.Role == MessageRole.Agent && textItem.Annotations.Count > 0)
246+
{
247+
string annotatedText = textItem.Text;
248+
249+
// If we have Text URL citation annotations, reformat the response to show title & URL for citations
250+
foreach (MessageTextAnnotation annotation in textItem.Annotations)
251+
{
252+
if (annotation is MessageTextUrlCitationAnnotation urlAnnotation)
253+
{
254+
annotatedText = annotatedText.Replace(
255+
urlAnnotation.Text,
256+
$" [see {urlAnnotation.UrlCitation.Title}] ({urlAnnotation.UrlCitation.Url})");
257+
}
258+
}
259+
Console.Write(annotatedText);
260+
}
261+
else
262+
{
263+
Console.Write(textItem.Text);
264+
}
245265
}
246266
else if (contentItem is MessageImageFileContent imageFileItem)
247267
{
@@ -250,6 +270,17 @@ foreach (ThreadMessage threadMessage in messages)
250270
Console.WriteLine();
251271
}
252272
}
273+
```
274+
## Step 5: Clean up resources
275+
276+
Clean up the resources from this sample.
277+
278+
```csharp
279+
280+
// Delete thread and agent
281+
agentClient.Threads.DeleteThread(thread.Id);
282+
agentClient.Administration.DeleteAgent(agent.Id);
283+
253284
```
254285

255286
:::zone-end

0 commit comments

Comments
 (0)