|
| 1 | +--- |
| 2 | +title: 'Setup an agent with standard setup and your own vnet in the Azure AI Agent Service' |
| 3 | +titleSuffix: Azure OpenAI |
| 4 | +description: Learn how to use your own vnet with the Azure AI Agent Service. |
| 5 | +services: cognitive-services |
| 6 | +manager: nitinme |
| 7 | +ms.service: azure-ai-agent-service |
| 8 | +ms.topic: how-to |
| 9 | +ms.date: 02/22/2025 |
| 10 | +author: fosteramanda |
| 11 | +ms.author: fosteramanda |
| 12 | +ms.custom: azure-ai-agents |
| 13 | +--- |
| 14 | + |
| 15 | +# QuickStart: Create a new network-secured agent with user-managed identity |
| 16 | + |
| 17 | +## Prerequisites |
| 18 | + |
| 19 | +1. An Azure subscription - [Create one for free](https://azure.microsoft.com/free/cognitive-services). |
| 20 | +2. [Python 3.8 or later](https://www.python.org/) |
| 21 | +3. Make the person deploying the template has the role: **Contributor** assigned at the resource group level and they are deploying this template in that specific resource group (specific role). [Learn more](https://learn.microsoft.com/azure/ai-studio/concepts/rbac-ai-studio) |
| 22 | +4. To deploy the bicep template and configure RBAC you need to have the role: **Role Based Access Administrator** at the subscription level. |
| 23 | + * Note: The **Owner** role at the subscription level satisfies this. |
| 24 | +5. Install [the Azure CLI and the machine learning extension](/azure/machine-learning/how-to-configure-cli). If you have the CLI already installed, make sure it's updated to the latest version. |
| 25 | +6. Register providers |
| 26 | + The following providers must be registered: |
| 27 | + |
| 28 | + * Microsoft.KeyVault |
| 29 | + * Microsoft.CognitiveServices |
| 30 | + * Microsoft.Storage |
| 31 | + * Microsoft.MachineLearningServices |
| 32 | + * Microsoft.Search |
| 33 | + * Microsoft.Network |
| 34 | + * To use Bing Search tool: Microsoft.Bing |
| 35 | + |
| 36 | + ```console |
| 37 | + az provider register --namespace 'Microsoft.KeyVault' |
| 38 | + az provider register --namespace 'Microsoft.CognitiveServices' |
| 39 | + az provider register --namespace 'Microsoft.Storage' |
| 40 | + az provider register --namespace 'Microsoft.MachineLearningServices' |
| 41 | + az provider register --namespace 'Microsoft.Search' |
| 42 | + # only to use Grounding with Bing Search tool |
| 43 | + az provider register --namespace 'Microsoft.Bing' |
| 44 | + ``` |
| 45 | + |
| 46 | +## Deploy the Bicep Template |
| 47 | + |
| 48 | +**Network Secured Setup**: Agents use customer-owned, single-tenant search and storage resources. With this setup, you have full control and visibility over these resources, but you will incur costs based on your usage. |
| 49 | + |
| 50 | +* Resources for the hub, project, storage account, key vault, AI Services, and Azure AI Search will be created for you. The AI Services, AI Search, and Azure Blob Storage account will be connected to your project/hub and a gpt-4o-mini model will be deployed in the westus2 region. |
| 51 | +* Customer owned resources will be secured with a provisioned managed network and authenticated with a User Managed Identity with the necessary RBAC permissions. Private links and DNS zones will be created on behalf of the customer to ensure network connectivity. |
| 52 | + |
| 53 | +<br/> |
| 54 | + |
| 55 | +<details> |
| 56 | +<summary><b> Bicep Technical Details</b> |
| 57 | +</summary> |
| 58 | + |
| 59 | +**The Bicep template automates the following configurations and resource provisions:** |
| 60 | +* Creates a User Assigned Identify. [Learn more](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-manage-user-assigned-managed-identities?pivots=identity-mi-methods-azp#create-a-user-assigned-managed-identity) |
| 61 | + * The User Assigned Managed Identity requires the following Role Based Access Roles: KeyVault Secret Officer, KeyVault Contributor , Storage Blob Data Owner, Storage Queue Data Contributor, Cognitive Services Contributor, Cognitive Services OpenAI User, Search Index Data Contributor, Search Service Contributor |
| 62 | + |
| 63 | +* Configures a managed virtual network with two subnet resources: |
| 64 | + * Azure Resource Subnet |
| 65 | + * Enables Service Endpoints for: |
| 66 | + * Microsoft.KeyVault |
| 67 | + * Microsoft.Storage |
| 68 | + * Microsoft.CognitiveServices |
| 69 | + * Agent Resource Subnet |
| 70 | + * Configured with Subnet Delegations for: |
| 71 | + * Microsoft.app/environments |
| 72 | +* Provisions Dependent Resources |
| 73 | + * Azure Key Vault, Azure Storage, AOAI/AI Services, and Azure AI Search resources are created. |
| 74 | + * All resources are configured with: |
| 75 | + * Disabled public network access |
| 76 | + * Private endpoints in the Azure Resource subnet |
| 77 | + * Private DNS integration enabled |
| 78 | + * User Assigned Identity for authentication |
| 79 | +* Creates a hub and project using the resources provisioned above and configures them to use the Agent Resource Subnet. |
| 80 | + * Accomplished by configuring the capabilityHost (a sub-resource of hub/project) to use the Agent Resource Subnet for network isolation and secure communication. |
| 81 | +</details> |
| 82 | + |
| 83 | +<br/> |
| 84 | + |
| 85 | +### Option 1: Auto-Deploy the Bicep Template |
| 86 | + |
| 87 | +| Template | Description | Auto-deploy | |
| 88 | +| ------------------- | -----------------------------------------------| -----------------------| |
| 89 | +| `network-secured-agent.bicep` | Deploy a network secured agent setup that uses User Managed Identity authentication on the Agent Connections. | [](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-quickstart-templates%2Frefs%2Fheads%2Fmaster%2Fquickstarts%2Fmicrosoft.azure-ai-agent-service%2Fnetwork-secured-agent%2Fazuredeploy.json) |
| 90 | + |
| 91 | +### Option 2: Manually Deploy the Bicep Template |
| 92 | + |
| 93 | +1. If you want to manually run the bicep templates, you can [download the template from GitHub](https://github.com/Azure/azure-quickstart-templates/tree/master/quickstarts/microsoft.azure-ai-agent-service/network-secured-agent). Download the following from the network-secured-agent folder: |
| 94 | + 1. main.bicep |
| 95 | + 1. azuredeploy.parameters.json |
| 96 | + 1. modules-network-secured folder |
| 97 | +1. To authenticate to your Azure subscription from the Azure CLI, use the following command: |
| 98 | + |
| 99 | + ```console |
| 100 | + az login |
| 101 | + ``` |
| 102 | + |
| 103 | +1. Create a resource group |
| 104 | + |
| 105 | + ```console |
| 106 | + az group create --name {my_resource_group} --location eastus |
| 107 | + ``` |
| 108 | + |
| 109 | + Make sure you have the role Azure AI Developer on the resource group you just created. |
| 110 | +1. Using the resource group you created in the previous step and one of the template files (either basic-agent-keys.bicep or basic-agent-identity.bicep), run one of the following commands: |
| 111 | + |
| 112 | + 1. To use default resource names, run: |
| 113 | + |
| 114 | + ```console |
| 115 | + az deployment group create --resource-group {my_resource_group} --template-file main.bicep |
| 116 | + ``` |
| 117 | + |
| 118 | + 1. To specify custom names for the hub, project, storage account, and/or Azure AI service resources (Note: a randomly generated suffix will be added to prevent accidental duplication), run: |
| 119 | + |
| 120 | + ```console |
| 121 | + az deployment group create --resource-group {my_resource_group} --template-file main.bicep --parameters aiHubName='your-hub-name' aiProjectName='your-project-name' storageName='your-storage-name' aiServicesName='your-ai-services-name' |
| 122 | + |
| 123 | + ``` |
| 124 | + |
| 125 | + 1. To customize additional parameters, including the OpenAI model deployment, download and edit the azuredeploy.parameters.json file, then run: |
| 126 | + |
| 127 | + ```console |
| 128 | + az deployment group create --resource-group {my_resource_group} --template-file main.bicep --parameters @azuredeploy.parameters.json |
| 129 | + ``` |
| 130 | + |
| 131 | +## Configure and run an agent |
| 132 | + |
| 133 | +| Component | Description | |
| 134 | +| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 135 | +| Agent | Custom AI that uses AI models in conjunction with tools. | |
| 136 | +| Tool | Tools help extend an agent’s ability to reliably and accurately respond during conversation. Such as connecting to user-defined knowledge bases to ground the model, or enabling web search to provide current information. | |
| 137 | +| Thread | A conversation session between an agent and a user. Threads store Messages and automatically handle truncation to fit content into a model’s context. | |
| 138 | +| Message | A message created by an agent or a user. Messages can include text, images, and other files. Messages are stored as a list on the Thread. | |
| 139 | +| Run | Activation of an agent to begin running based on the contents of Thread. The agent uses its configuration and Thread’s Messages to perform tasks by calling models and tools. As part of a Run, the agent appends Messages to the Thread. | |
| 140 | +| Run Step | A detailed list of steps the agent took as part of a Run. An agent can call tools or create Messages during its run. Examining Run Steps allows you to understand how the agent is getting to its results. | |
| 141 | + |
| 142 | +**The following code shows how to create and run an agent using Python (Azure SDK):** |
| 143 | + |
| 144 | +* C#: See the [C# quickstart](https://learn.microsoft.com/azure/ai-services/agents/quickstart?pivots=programming-language-csharp) |
| 145 | +* Python OpenAI SDK: See the [Python OpenAI SDK quickstart](https://learn.microsoft.com/azure/ai-services/agents/quickstart?pivots=programming-language-python-openai) |
| 146 | + |
| 147 | +Run the following commands to install the python packages. |
| 148 | + |
| 149 | +```console |
| 150 | +pip install azure-ai-projects |
| 151 | +pip install azure-identity |
| 152 | +``` |
| 153 | + |
| 154 | +Use the following code to create and run an agent. To run this code, you will need to create a connection string using information from your project. This string is in the format: |
| 155 | + |
| 156 | +`<HostName>;<AzureSubscriptionId>;<ResourceGroup>;<ProjectName>` |
| 157 | + |
| 158 | +> [!TIP] |
| 159 | +> You can also find your connection string in the **overview** for your project in the [Azure AI Foundry portal](https://ai.azure.com/), under **Project details** > **Project connection string**. |
| 160 | +> :::image type="content" source="portal-connection-string.png" alt-text="A screenshot showing the connection string in the Azure AI Foundry portal." lightbox="portal-connection-string.png"::: |
| 161 | +
|
| 162 | +`HostName` can be found by navigating to your `discovery_url` and removing the leading `https://` and trailing `/discovery`. To find your `discovery_url`, run this CLI command: |
| 163 | + |
| 164 | +```azurecli |
| 165 | +az ml workspace show -n {project_name} --resource-group {resource_group_name} --query discovery_url |
| 166 | +``` |
| 167 | + |
| 168 | +For example, your connection string may look something like: |
| 169 | + |
| 170 | +`eastus.api.azureml.ms;12345678-abcd-1234-9fc6-62780b3d3e05;my-resource-group;my-project-name` |
| 171 | + |
| 172 | +Set this connection string as an environment variable named `PROJECT_CONNECTION_STRING`. |
| 173 | + |
| 174 | +```python |
| 175 | +import os |
| 176 | +from azure.ai.projects import AIProjectClient |
| 177 | +from azure.ai.projects.models import CodeInterpreterTool |
| 178 | +from azure.identity import DefaultAzureCredential |
| 179 | +from typing import Any |
| 180 | +from pathlib import Path |
| 181 | + |
| 182 | +# Create an Azure AI Client from a connection string, copied from your Azure AI Foundry project. |
| 183 | +# At the moment, it should be in the format "<HostName>;<AzureSubscriptionId>;<ResourceGroup>;<ProjectName>" |
| 184 | +# HostName can be found by navigating to your discovery_url and removing the leading "https://" and trailing "/discovery" |
| 185 | +# To find your discovery_url, run the CLI command: az ml workspace show -n {project_name} --resource-group {resource_group_name} --query discovery_url |
| 186 | +# Project Connection example: eastus.api.azureml.ms;12345678-abcd-1234-9fc6-62780b3d3e05;my-resource-group;my-project-name |
| 187 | +# Customer needs to login to Azure subscription via Azure CLI and set the environment variables |
| 188 | + |
| 189 | +project_client = AIProjectClient.from_connection_string( |
| 190 | + credential=DefaultAzureCredential(), conn_str=os.environ["PROJECT_CONNECTION_STRING"] |
| 191 | +) |
| 192 | + |
| 193 | +with project_client: |
| 194 | + # Create an instance of the CodeInterpreterTool |
| 195 | + code_interpreter = CodeInterpreterTool() |
| 196 | + |
| 197 | + # The CodeInterpreterTool needs to be included in creation of the agent |
| 198 | + agent = project_client.agents.create_agent( |
| 199 | + model="gpt-4o-mini", |
| 200 | + name="my-agent", |
| 201 | + instructions="You are helpful agent", |
| 202 | + tools=code_interpreter.definitions, |
| 203 | + tool_resources=code_interpreter.resources, |
| 204 | + ) |
| 205 | + print(f"Created agent, agent ID: {agent.id}") |
| 206 | + |
| 207 | + # Create a thread |
| 208 | + thread = project_client.agents.create_thread() |
| 209 | + print(f"Created thread, thread ID: {thread.id}") |
| 210 | + |
| 211 | + # Create a message |
| 212 | + message = project_client.agents.create_message( |
| 213 | + thread_id=thread.id, |
| 214 | + role="user", |
| 215 | + content="Could you please create a bar chart for the operating profit using the following data and provide the file to me? Company A: $1.2 million, Company B: $2.5 million, Company C: $3.0 million, Company D: $1.8 million", |
| 216 | + ) |
| 217 | + print(f"Created message, message ID: {message.id}") |
| 218 | + |
| 219 | + # Run the agent |
| 220 | + run = project_client.agents.create_and_process_run(thread_id=thread.id, assistant_id=agent.id) |
| 221 | + print(f"Run finished with status: {run.status}") |
| 222 | + |
| 223 | + if run.status == "failed": |
| 224 | + # Check if you got "Rate limit is exceeded.", then you want to get more quota |
| 225 | + print(f"Run failed: {run.last_error}") |
| 226 | + |
| 227 | + # Get messages from the thread |
| 228 | + messages = project_client.agents.list_messages(thread_id=thread.id) |
| 229 | + print(f"Messages: {messages}") |
| 230 | + |
| 231 | + # Get the last message from the sender |
| 232 | + last_msg = messages.get_last_text_message_by_sender("assistant") |
| 233 | + if last_msg: |
| 234 | + print(f"Last Message: {last_msg.text.value}") |
| 235 | + |
| 236 | + # Generate an image file for the bar chart |
| 237 | + for image_content in messages.image_contents: |
| 238 | + print(f"Image File ID: {image_content.image_file.file_id}") |
| 239 | + file_name = f"{image_content.image_file.file_id}_image_file.png" |
| 240 | + project_client.agents.save_file(file_id=image_content.image_file.file_id, file_name=file_name) |
| 241 | + print(f"Saved image file to: {Path.cwd() / file_name}") |
| 242 | + |
| 243 | + # Print the file path(s) from the messages |
| 244 | + for file_path_annotation in messages.file_path_annotations: |
| 245 | + print(f"File Paths:") |
| 246 | + print(f"Type: {file_path_annotation.type}") |
| 247 | + print(f"Text: {file_path_annotation.text}") |
| 248 | + print(f"File ID: {file_path_annotation.file_path.file_id}") |
| 249 | + print(f"Start Index: {file_path_annotation.start_index}") |
| 250 | + print(f"End Index: {file_path_annotation.end_index}") |
| 251 | + project_client.agents.save_file(file_id=file_path_annotation.file_path.file_id, file_name=Path(file_path_annotation.text).name) |
| 252 | + |
| 253 | + # Delete the agent once done |
| 254 | + project_client.agents.delete_agent(agent.id) |
| 255 | + print("Deleted agent") |
| 256 | +``` |
0 commit comments