|
| 1 | +# Azure AI Discovery client library for .NET |
| 2 | + |
| 3 | +The Azure AI Discovery client library for .NET provides two clients for interacting with Microsoft Discovery services: |
| 4 | + |
| 5 | +- **`WorkspaceClient`** — manage investigations, conversations, tasks, and tools in a Discovery workspace. |
| 6 | +- **`BookshelfClient`** — manage knowledge bases and knowledge base versions. |
| 7 | + |
| 8 | +[Source code][source_code] | [Package (NuGet)][nuget] | [API reference documentation][api_reference] | [Product documentation][product_docs] | [Samples][samples] |
| 9 | + |
| 10 | +## Getting started |
| 11 | + |
| 12 | +### Install the package |
| 13 | + |
| 14 | +Install the client library for .NET with [NuGet][nuget]: |
| 15 | + |
| 16 | +```dotnetcli |
| 17 | +dotnet add package Azure.AI.Discovery --prerelease |
| 18 | +``` |
| 19 | + |
| 20 | +### Prerequisites |
| 21 | + |
| 22 | +- An [Azure subscription][azure_sub]. |
| 23 | +- An existing Microsoft Discovery workspace or bookshelf instance. |
| 24 | +- The client library targets `netstandard2.0`, `net8.0`, and `net10.0`. |
| 25 | + |
| 26 | +### Authenticate the client |
| 27 | + |
| 28 | +Both clients use Microsoft Entra ID (Azure Active Directory) token authentication. Use the [Azure.Identity][azure_identity] library to obtain credentials: |
| 29 | + |
| 30 | +```dotnetcli |
| 31 | +dotnet add package Azure.Identity |
| 32 | +``` |
| 33 | + |
| 34 | +```C# Snippet:CreateDiscoveryClients |
| 35 | +WorkspaceClient workspaceClient = new WorkspaceClient( |
| 36 | + new Uri("https://<workspaceName>.workspace.discovery.azure.com"), |
| 37 | + new DefaultAzureCredential()); |
| 38 | + |
| 39 | +BookshelfClient bookshelfClient = new BookshelfClient( |
| 40 | + new Uri("https://<bookshelfName>.bookshelf.discovery.azure.com"), |
| 41 | + new DefaultAzureCredential()); |
| 42 | +``` |
| 43 | + |
| 44 | +### Service API versions |
| 45 | + |
| 46 | +The client library targets the latest service API version by default. You can optionally select a supported service API version when instantiating a client: |
| 47 | + |
| 48 | +```C# Snippet:CreateDiscoveryClientForSpecificApiVersion |
| 49 | +WorkspaceClientOptions options = new WorkspaceClientOptions( |
| 50 | + WorkspaceClientOptions.ServiceVersion.V2026_02_01_Preview); |
| 51 | + |
| 52 | +WorkspaceClient client = new WorkspaceClient( |
| 53 | + new Uri("https://<workspaceName>.workspace.discovery.azure.com"), |
| 54 | + new DefaultAzureCredential(), |
| 55 | + options); |
| 56 | +``` |
| 57 | + |
| 58 | +## Key concepts |
| 59 | + |
| 60 | +### WorkspaceClient |
| 61 | + |
| 62 | +`WorkspaceClient` is the entry point for Discovery workspace operations. It exposes four sub-clients: |
| 63 | + |
| 64 | +- **`DiscoveryInvestigationsClient`** — create and manage research investigations within a project. Each investigation can have a Discovery Engine that autonomously explores data and generates insights. |
| 65 | +- **`DiscoveryConversationsClient`** — interact with the Discovery Engine through conversational sessions tied to an investigation. |
| 66 | +- **`DiscoveryTasksClient`** — create, assign, and track units of work within an investigation, such as research steps or follow-up actions. |
| 67 | +- **`DiscoveryToolsClient`** — run compute jobs on supercomputer node pools and monitor their status and resource usage. |
| 68 | + |
| 69 | +Sub-clients are obtained from a `WorkspaceClient` instance: |
| 70 | + |
| 71 | +```C# |
| 72 | +DiscoveryInvestigationsClient investigations = workspaceClient.GetDiscoveryInvestigationsClient(); |
| 73 | +DiscoveryConversationsClient conversations = workspaceClient.GetDiscoveryConversationsClient(); |
| 74 | +DiscoveryTasksClient tasks = workspaceClient.GetDiscoveryTasksClient(); |
| 75 | +DiscoveryToolsClient tools = workspaceClient.GetDiscoveryToolsClient(); |
| 76 | +``` |
| 77 | + |
| 78 | +### BookshelfClient |
| 79 | + |
| 80 | +`BookshelfClient` is the entry point for knowledge base management. It exposes two sub-clients: |
| 81 | + |
| 82 | +- **`KnowledgeBases`** — list available knowledge bases. |
| 83 | +- **`KnowledgeBaseVersions`** — create, update, index, and manage versions of knowledge bases backed by storage assets. |
| 84 | + |
| 85 | +```C# |
| 86 | +KnowledgeBases knowledgeBases = bookshelfClient.GetKnowledgeBasesClient(); |
| 87 | +KnowledgeBaseVersions knowledgeBaseVersions = bookshelfClient.GetKnowledgeBaseVersionsClient(); |
| 88 | +``` |
| 89 | + |
| 90 | +### Long-running operations |
| 91 | + |
| 92 | +Operations such as deleting an investigation or indexing a knowledge base version are modeled as Azure SDK long-running operations (`Operation<T>`). Pass `WaitUntil.Completed` to block until the operation finishes, or `WaitUntil.Started` to receive the operation handle immediately and poll later. |
| 93 | + |
| 94 | +### Thread safety |
| 95 | + |
| 96 | +All client instance methods are thread-safe and independent of each other ([guideline][thread_safety]). This means it is safe — and recommended — to reuse a single client instance across threads. |
| 97 | + |
| 98 | +## Examples |
| 99 | + |
| 100 | +The following sections provide code snippets covering common scenarios. For complete runnable samples, see the [Samples][samples] directory. |
| 101 | + |
| 102 | +### Create and manage an investigation |
| 103 | + |
| 104 | +```C# Snippet:CreateAndManageInvestigation |
| 105 | +WorkspaceClient client = new WorkspaceClient( |
| 106 | + new Uri("https://<workspaceName>.workspace.discovery.azure.com"), |
| 107 | + new DefaultAzureCredential()); |
| 108 | + |
| 109 | +DiscoveryInvestigationsClient investigations = client.GetDiscoveryInvestigationsClient(); |
| 110 | + |
| 111 | +string projectName = "my-project"; |
| 112 | +string investigationName = "sample-investigation"; |
| 113 | + |
| 114 | +// Create or replace an investigation. |
| 115 | +DiscoveryInvestigation resource = new DiscoveryInvestigation |
| 116 | +{ |
| 117 | + DisplayName = "Sample Investigation", |
| 118 | + Description = "Investigating anomalies in dataset X", |
| 119 | +}; |
| 120 | + |
| 121 | +Response<DiscoveryInvestigation> created = await investigations.CreateOrReplaceAsync( |
| 122 | + projectName, investigationName, resource); |
| 123 | + |
| 124 | +Console.WriteLine($"Created investigation: {created.Value.Name}"); |
| 125 | + |
| 126 | +// Start the Discovery Engine for the investigation. |
| 127 | +Response<DiscoveryEngine> engine = await investigations.StartDiscoveryEngineAsync( |
| 128 | + projectName, investigationName); |
| 129 | + |
| 130 | +Console.WriteLine($"Discovery Engine status: {engine.Value.DiscoveryEngineStatus}"); |
| 131 | +``` |
| 132 | + |
| 133 | +### Create and manage tasks |
| 134 | + |
| 135 | +```C# Snippet:CreateAndManageTasks |
| 136 | +WorkspaceClient client = new WorkspaceClient( |
| 137 | + new Uri("https://<workspaceName>.workspace.discovery.azure.com"), |
| 138 | + new DefaultAzureCredential()); |
| 139 | + |
| 140 | +DiscoveryTasksClient tasks = client.GetDiscoveryTasksClient(); |
| 141 | + |
| 142 | +string projectName = "my-project"; |
| 143 | +string investigationName = "sample-investigation"; |
| 144 | + |
| 145 | +DiscoveryTask task = new DiscoveryTask |
| 146 | +{ |
| 147 | + Title = "Analyze compound interactions", |
| 148 | + Description = "Review the interaction data for compounds A and B", |
| 149 | + Priority = TaskPriority.High, |
| 150 | + AssignedTo = new TaskAssignee("researcher-agent", ByType.Application), |
| 151 | + InvestigationId = $"/projects/{projectName}/investigations/{investigationName}", |
| 152 | +}; |
| 153 | + |
| 154 | +Response<DiscoveryTask> created = await tasks.CreateAsync(projectName, investigationName, task); |
| 155 | +Console.WriteLine($"Created task: {created.Value.Title} ({created.Value.Status})"); |
| 156 | + |
| 157 | +// Add a comment to the task. |
| 158 | +await tasks.AddCommentAsync( |
| 159 | + created.Value.Name, |
| 160 | + projectName, |
| 161 | + investigationName, |
| 162 | + new TaskComment("sample-user", ByType.User, "Initial analysis shows promising results.")); |
| 163 | + |
| 164 | +// List tasks with a filter. |
| 165 | +await foreach (DiscoveryTask t in tasks.GetAllAsync(projectName, investigationName, filter: "status eq 'New'")) |
| 166 | +{ |
| 167 | + Console.WriteLine($"{t.Name}: {t.Title}"); |
| 168 | +} |
| 169 | +``` |
| 170 | + |
| 171 | +### Run a tool on compute |
| 172 | + |
| 173 | +```C# Snippet:RunToolOnCompute |
| 174 | +WorkspaceClient client = new WorkspaceClient( |
| 175 | + new Uri("https://<workspaceName>.workspace.discovery.azure.com"), |
| 176 | + new DefaultAzureCredential()); |
| 177 | + |
| 178 | +DiscoveryToolsClient tools = client.GetDiscoveryToolsClient(); |
| 179 | + |
| 180 | +Operation<RunResult> run = await tools.RunAsync( |
| 181 | + WaitUntil.Completed, |
| 182 | + projectName: "my-project", |
| 183 | + toolId: new ResourceIdentifier("/subscriptions/.../tools/my-tool"), |
| 184 | + nodePoolIds: new[] { new ResourceIdentifier("/subscriptions/.../nodePools/my-pool") }, |
| 185 | + command: "echo \"Hello from Discovery\""); |
| 186 | + |
| 187 | +Console.WriteLine($"Run completed: {run.Value.Status}"); |
| 188 | +``` |
| 189 | + |
| 190 | +### Manage knowledge base versions |
| 191 | + |
| 192 | +```C# Snippet:ManageKnowledgeBaseVersions |
| 193 | +BookshelfClient client = new BookshelfClient( |
| 194 | + new Uri("https://<bookshelfName>.bookshelf.discovery.azure.com"), |
| 195 | + new DefaultAzureCredential()); |
| 196 | + |
| 197 | +KnowledgeBases knowledgeBases = client.GetKnowledgeBasesClient(); |
| 198 | +KnowledgeBaseVersions versions = client.GetKnowledgeBaseVersionsClient(); |
| 199 | + |
| 200 | +// List knowledge bases. |
| 201 | +await foreach (KnowledgeBase kb in knowledgeBases.GetAllAsync()) |
| 202 | +{ |
| 203 | + Console.WriteLine($"Knowledge base: {kb.Name}"); |
| 204 | +} |
| 205 | + |
| 206 | +// Create a knowledge base version. CreateOrUpdate is currently exposed as a protocol method |
| 207 | +// (no typed convenience overload), so build a RequestContent from the typed model. |
| 208 | +string knowledgeBaseName = "my-kb"; |
| 209 | +string versionName = "v1"; |
| 210 | + |
| 211 | +KnowledgeBaseVersion resource = new KnowledgeBaseVersion( |
| 212 | + description: "Research data for compound analysis", |
| 213 | + copilotInstruction: "Use this to query information about compound interactions.") |
| 214 | +{ |
| 215 | + StorageAssetReferences = |
| 216 | + { |
| 217 | + new StorageAssetReference(new ResourceIdentifier("/subscriptions/.../storageAssets/my-asset")) |
| 218 | + { |
| 219 | + UserAssignedIdentity = new ResourceIdentifier("/subscriptions/.../userAssignedIdentities/my-id"), |
| 220 | + }, |
| 221 | + }, |
| 222 | +}; |
| 223 | + |
| 224 | +Response createResponse = await versions.CreateOrUpdateAsync( |
| 225 | + knowledgeBaseName, versionName, RequestContent.Create(resource)); |
| 226 | +Console.WriteLine($"CreateOrUpdate status: {createResponse.Status}"); |
| 227 | + |
| 228 | +// Start indexing as a long-running operation. |
| 229 | +Operation<KnowledgeBaseVersion> indexing = await versions.StartIndexingAsync( |
| 230 | + WaitUntil.Completed, |
| 231 | + knowledgeBaseName, |
| 232 | + versionName, |
| 233 | + nodePoolId: "/subscriptions/.../nodePools/my-pool"); |
| 234 | + |
| 235 | +Console.WriteLine($"Indexed version: {indexing.Value.Version}"); |
| 236 | +``` |
| 237 | + |
| 238 | +## Troubleshooting |
| 239 | + |
| 240 | +### Logging |
| 241 | + |
| 242 | +This library uses the standard Azure.Core diagnostics pipeline. Enable detailed HTTP request/response logging by adding an `AzureEventSourceListener` to your application: |
| 243 | + |
| 244 | +```C# |
| 245 | +using Azure.Core.Diagnostics; |
| 246 | +using System.Diagnostics.Tracing; |
| 247 | + |
| 248 | +using AzureEventSourceListener listener = AzureEventSourceListener.CreateConsoleLogger(EventLevel.Verbose); |
| 249 | +``` |
| 250 | + |
| 251 | +See the [Azure SDK logging guidelines][azure_logging] for more details. |
| 252 | + |
| 253 | +### Exceptions |
| 254 | + |
| 255 | +Azure AI Discovery clients raise exceptions defined in [Azure.Core][azure_core_exceptions]. For example, if you try to get an investigation that does not exist, `RequestFailedException` is thrown with `Status == 404`: |
| 256 | + |
| 257 | +```C# |
| 258 | +try |
| 259 | +{ |
| 260 | + Response<DiscoveryInvestigation> investigation = await investigations.GetAsync( |
| 261 | + "my-project", "nonexistent"); |
| 262 | +} |
| 263 | +catch (RequestFailedException ex) when (ex.Status == 404) |
| 264 | +{ |
| 265 | + Console.WriteLine($"Investigation not found: {ex.Message}"); |
| 266 | +} |
| 267 | +``` |
| 268 | + |
| 269 | +## Next steps |
| 270 | + |
| 271 | +- Browse the [samples][samples] for runnable code that demonstrates common scenarios. |
| 272 | +- Read the [Microsoft Discovery product documentation][product_docs]. |
| 273 | + |
| 274 | +## Contributing |
| 275 | + |
| 276 | +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 https://cla.microsoft.com. |
| 277 | + |
| 278 | +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., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. |
| 279 | + |
| 280 | +This project has adopted the [Microsoft Open Source Code of Conduct][code_of_conduct]. For more information, see the [Code of Conduct FAQ][code_of_conduct_faq] or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. |
| 281 | + |
| 282 | +<!-- LINKS --> |
| 283 | +[source_code]: https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/discovery/Azure.AI.Discovery/src |
| 284 | +[nuget]: https://www.nuget.org/packages/Azure.AI.Discovery |
| 285 | +[api_reference]: https://learn.microsoft.com/dotnet/api/azure.ai.discovery |
| 286 | +[product_docs]: https://learn.microsoft.com/azure/microsoft-discovery/ |
| 287 | +[samples]: https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/discovery/Azure.AI.Discovery/samples |
| 288 | +[azure_sub]: https://azure.microsoft.com/free/dotnet/ |
| 289 | +[azure_identity]: https://learn.microsoft.com/dotnet/api/overview/azure/identity-readme |
| 290 | +[azure_core_exceptions]: https://learn.microsoft.com/dotnet/api/azure.requestfailedexception |
| 291 | +[azure_logging]: https://learn.microsoft.com/dotnet/azure/sdk/logging |
| 292 | +[thread_safety]: https://azure.github.io/azure-sdk/dotnet_introduction.html#dotnet-service-methods-thread-safety |
| 293 | +[code_of_conduct]: https://opensource.microsoft.com/codeofconduct/ |
| 294 | +[code_of_conduct_faq]: https://opensource.microsoft.com/codeofconduct/faq/ |
0 commit comments