Azure.AI.Agents.Persistent (.NET)
SDK bas niveau pour créer et gérer des agents d'IA persistants avec threads, messages, exécutions et outils.
Installation
dotnet add package Azure.AI.Agents.Persistent --prerelease
dotnet add package Azure.Identity
Versions actuelles : Stable v1.1.0, Preview v1.2.0-beta.8
Variables d'environnement
PROJECT_ENDPOINT=https://<resource>.services.ai.azure.com/api/projects/<project>
MODEL_DEPLOYMENT_NAME=gpt-4o-mini
AZURE_BING_CONNECTION_ID=<bing-connection-resource-id>
AZURE_AI_SEARCH_CONNECTION_ID=<search-connection-resource-id>
AZURE_TOKEN_CREDENTIALS=prod
Authentification
using Azure.AI.Agents.Persistent;
using Azure.Identity;
var projectEndpoint = Environment.GetEnvironmentVariable("PROJECT_ENDPOINT");
var credential = new DefaultAzureCredential(
DefaultAzureCredential.DefaultEnvironmentVariableName
);
PersistentAgentsClient client = new(projectEndpoint, credential);
Hiérarchie du client
PersistentAgentsClient
├── Administration → Opérations CRUD sur les agents
├── Threads → Gestion des threads
├── Messages → Opérations sur les messages
├── Runs → Exécution des runs et streaming
├── Files → Upload/téléchargement de fichiers
└── VectorStores → Gestion des vector stores
Flux de travail principal
1. Créer un agent
var modelDeploymentName = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME");
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Tuteur de maths",
instructions: "Tu es un tuteur personnel de mathématiques. Écris et exécute du code pour répondre aux questions de maths.",
tools: [new CodeInterpreterToolDefinition()]
);
2. Créer un thread et un message
PersistentAgentThread thread = await client.Threads.CreateThreadAsync();
await client.Messages.CreateMessageAsync(
thread.Id,
MessageRole.User,
"J'ai besoin de résoudre l'équation `3x + 11 = 14`. Peux-tu m'aider ?"
);
3. Exécuter l'agent (par polling)
ThreadRun run = await client.Runs.CreateRunAsync(
thread.Id,
agent.Id,
additionalInstructions: "Veuillez vous adresser à l'utilisateur en tant que Jane Doe."
);
while (run.Status == RunStatus.Queued || run.Status == RunStatus.InProgress)
{
await Task.Delay(TimeSpan.FromMilliseconds(500));
run = await client.Runs.GetRunAsync(thread.Id, run.Id);
}
await foreach (PersistentThreadMessage message in client.Messages.GetMessagesAsync(
threadId: thread.Id,
order: ListSortOrder.Ascending))
{
Console.Write($"{message.Role}: ");
foreach (MessageContent content in message.ContentItems)
{
if (content is MessageTextContent textContent)
Console.WriteLine(textContent.Text);
}
}
4. Réponse en streaming
AsyncCollectionResult<StreamingUpdate> stream = client.Runs.CreateRunStreamingAsync(
thread.Id,
agent.Id
);
await foreach (StreamingUpdate update in stream)
{
if (update.UpdateKind == StreamingUpdateReason.RunCreated)
{
Console.WriteLine("--- Exécution démarrée ! ---");
}
else if (update is MessageContentUpdate contentUpdate)
{
Console.Write(contentUpdate.Text);
}
else if (update.UpdateKind == StreamingUpdateReason.RunCompleted)
{
Console.WriteLine("\n--- Exécution terminée ! ---");
}
}
5. Appel de fonctions (Function Calling)
FunctionToolDefinition weatherTool = new(
name: "getCurrentWeather",
description: "Obtient la météo actuelle à un endroit donné.",
parameters: BinaryData.FromObjectAsJson(new
{
Type = "object",
Properties = new
{
Location = new { Type = "string", Description = "Ville et état, ex. San Francisco, CA" },
Unit = new { Type = "string", Enum = new[] { "c", "f" } }
},
Required = new[] { "location" }
}, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })
);
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Bot météo",
instructions: "Tu es un bot météo.",
tools: [weatherTool]
);
while (run.Status == RunStatus.Queued || run.Status == RunStatus.InProgress)
{
await Task.Delay(500);
run = await client.Runs.GetRunAsync(thread.Id, run.Id);
if (run.Status == RunStatus.RequiresAction
&& run.RequiredAction is SubmitToolOutputsAction submitAction)
{
List<ToolOutput> outputs = [];
foreach (RequiredToolCall toolCall in submitAction.ToolCalls)
{
if (toolCall is RequiredFunctionToolCall funcCall)
{
string result = ExecuteFunction(funcCall.Name, funcCall.Arguments);
outputs.Add(new ToolOutput(toolCall, result));
}
}
run = await client.Runs.SubmitToolOutputsToRunAsync(run, outputs, toolApprovals: null);
}
}
6. Recherche de fichiers avec Vector Store
PersistentAgentFileInfo file = await client.Files.UploadFileAsync(
filePath: "document.txt",
purpose: PersistentAgentFilePurpose.Agents
);
PersistentAgentsVectorStore vectorStore = await client.VectorStores.CreateVectorStoreAsync(
fileIds: [file.Id],
name: "mon_vector_store"
);
FileSearchToolResource fileSearchResource = new();
fileSearchResource.VectorStoreIds.Add(vectorStore.Id);
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Assistant documentaire",
instructions: "Tu aides les utilisateurs à trouver des informations dans les documents.",
tools: [new FileSearchToolDefinition()],
toolResources: new ToolResources { FileSearch = fileSearchResource }
);
7. Bing Grounding
var bingConnectionId = Environment.GetEnvironmentVariable("AZURE_BING_CONNECTION_ID");
BingGroundingToolDefinition bingTool = new(
new BingGroundingSearchToolParameters(
[new BingGroundingSearchConfiguration(bingConnectionId)]
)
);
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Agent de recherche",
instructions: "Utilise Bing pour répondre aux questions sur l'actualité.",
tools: [bingTool]
);
8. Azure AI Search
AzureAISearchToolResource searchResource = new(
connectionId: searchConnectionId,
indexName: "my_index",
topK: 5,
filter: "category eq 'documentation'",
queryType: AzureAISearchQueryType.Simple
);
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Agent de recherche",
instructions: "Cherche dans l'index de documentation pour répondre aux questions.",
tools: [new AzureAISearchToolDefinition()],
toolResources: new ToolResources { AzureAISearch = searchResource }
);
9. Nettoyage
await client.Threads.DeleteThreadAsync(thread.Id);
await client.Administration.DeleteAgentAsync(agent.Id);
await client.VectorStores.DeleteVectorStoreAsync(vectorStore.Id);
await client.Files.DeleteFileAsync(file.Id);
Outils disponibles
| Outil | Classe | Objectif |
|---|
| Interpréteur de code | CodeInterpreterToolDefinition | Exécuter du code Python, générer des visualisations |
| Recherche de fichiers | FileSearchToolDefinition | Rechercher dans les fichiers uploadés via des vector stores |
| Appel de fonctions | FunctionToolDefinition | Appeler des fonctions personnalisées |
| Bing Grounding | BingGroundingToolDefinition | Recherche web via Bing |
| Azure AI Search | AzureAISearchToolDefinition | Rechercher dans les index Azure AI Search |
| OpenAPI | OpenApiToolDefinition | Appeler des API externes via une spécification OpenAPI |
| Azure Functions | AzureFunctionToolDefinition | Invoquer des Azure Functions |
| MCP | MCPToolDefinition | Outils du protocole de contexte de modèle (Model Context Protocol) |
| SharePoint | SharepointToolDefinition | Accéder au contenu SharePoint |
| Microsoft Fabric | MicrosoftFabricToolDefinition | Accéder aux données Fabric |
Types de mises à jour en streaming
| Type de mise à jour | Description |
|---|
StreamingUpdateReason.RunCreated | Exécution démarrée |
StreamingUpdateReason.RunInProgress | Exécution en cours |
StreamingUpdateReason.RunCompleted | Exécution terminée |
StreamingUpdateReason.RunFailed | Exécution en erreur |
MessageContentUpdate | Morceau de contenu texte |
RunStepUpdate | Changement d'état d'une étape |
Référence des types clés
| Type | Objectif |
|---|
PersistentAgentsClient | Point d'entrée principal |
PersistentAgent | Agent avec modèle, instructions, outils |
PersistentAgentThread | Thread de conversation |
PersistentThreadMessage | Message dans un thread |
ThreadRun | Exécution d'un agent sur un thread |
RunStatus | En file d'attente, En cours, Action requise, Terminé, Échoué |
ToolResources | Ressources d'outils combinées |
ToolOutput | Réponse d'appel de fonction |
Bonnes pratiques
- Toujours libérer les clients — Utiliser des instructions
using ou un libéré explicite
- Interroger avec des délais appropriés — 500ms recommandé entre les vérifications d'état
- Nettoyer les ressources — Supprimer les threads et les agents après utilisation
- Gérer tous les statuts d'exécution — Vérifier
RequiresAction, Failed, Cancelled
- Utiliser le streaming pour une UX en temps réel — Meilleure expérience utilisateur que le polling
- Stocker les ID, pas les objets — Référencer les agents/threads par leur ID
- Utiliser les méthodes asynchrones — Toutes les opérations doivent être async
Gestion des erreurs
using Azure;
try
{
var agent = await client.Administration.CreateAgentAsync(...);
}
catch (RequestFailedException ex) when (ex.Status == 404)
{
Console.WriteLine("Ressource non trouvée");
}
catch (RequestFailedException ex)
{
Console.WriteLine($"Erreur : {ex.Status} - {ex.ErrorCode}: {ex.Message}");
}
SDK associés
| SDK | Objectif | Installation |
|---|
Azure.AI.Agents.Persistent | Agents bas niveau (ce SDK) | dotnet add package Azure.AI.Agents.Persistent |
Azure.AI.Projects | Client projet haut niveau | dotnet add package Azure.AI.Projects |
Liens de référence