Azure.AI.Agents.Persistent (.NET)
SDK de baixo nível para criar e gerenciar agentes de IA persistentes com threads, mensagens, execuções e ferramentas.
Instalação
dotnet add package Azure.AI.Agents.Persistent --prerelease
dotnet add package Azure.Identity
Versões Atuais: Estável v1.1.0, Pré-visualização v1.2.0-beta.8
Variáveis de Ambiente
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
Autenticação
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);
Hierarquia do Cliente
PersistentAgentsClient
├── Administration → Operações CRUD de agente
├── Threads → Gerenciamento de threads
├── Messages → Operações de mensagens
├── Runs → Execução de runs e streaming
├── Files → Upload/download de arquivos
└── VectorStores → Gerenciamento de vector stores
Fluxo de Trabalho Principal
1. Criar Agente
var modelDeploymentName = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME");
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Math Tutor",
instructions: "You are a personal math tutor. Write and run code to answer math questions.",
tools: [new CodeInterpreterToolDefinition()]
);
2. Criar Thread e Mensagem
PersistentAgentThread thread = await client.Threads.CreateThreadAsync();
await client.Messages.CreateMessageAsync(
thread.Id,
MessageRole.User,
"I need to solve the equation `3x + 11 = 14`. Can you help me?"
);
3. Executar Agente (Polling)
ThreadRun run = await client.Runs.CreateRunAsync(
thread.Id,
agent.Id,
additionalInstructions: "Please address the user as Jane Doe."
);
do
{
await Task.Delay(TimeSpan.FromMilliseconds(500));
run = await client.Runs.GetRunAsync(thread.Id, run.Id);
}
while (run.Status == RunStatus.Queued || run.Status == RunStatus.InProgress);
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. Resposta em Streaming
AsyncCollectionResult<StreamingUpdate> stream = client.Runs.CreateRunStreamingAsync(
thread.Id,
agent.Id
);
await foreach (StreamingUpdate update in stream)
{
if (update.UpdateKind == StreamingUpdateReason.RunCreated)
{
Console.WriteLine("--- Run iniciada! ---");
}
else if (update is MessageContentUpdate contentUpdate)
{
Console.Write(contentUpdate.Text);
}
else if (update.UpdateKind == StreamingUpdateReason.RunCompleted)
{
Console.WriteLine("\n--- Run concluída! ---");
}
}
5. Chamada de Função
FunctionToolDefinition weatherTool = new(
name: "getCurrentWeather",
description: "Gets the current weather at a location.",
parameters: BinaryData.FromObjectAsJson(new
{
Type = "object",
Properties = new
{
Location = new { Type = "string", Description = "City and state, e.g. 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: "Weather Bot",
instructions: "You are a weather bot.",
tools: [weatherTool]
);
do
{
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);
}
}
while (run.Status == RunStatus.Queued || run.Status == RunStatus.InProgress);
6. Busca de Arquivos com Vector Store
PersistentAgentFileInfo file = await client.Files.UploadFileAsync(
filePath: "document.txt",
purpose: PersistentAgentFilePurpose.Agents
);
PersistentAgentsVectorStore vectorStore = await client.VectorStores.CreateVectorStoreAsync(
fileIds: [file.Id],
name: "my_vector_store"
);
FileSearchToolResource fileSearchResource = new();
fileSearchResource.VectorStoreIds.Add(vectorStore.Id);
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Document Assistant",
instructions: "You help users find information in documents.",
tools: [new FileSearchToolDefinition()],
toolResources: new ToolResources { FileSearch = fileSearchResource }
);
7. Ancoragem no Bing (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: "Search Agent",
instructions: "Use Bing to answer questions about current events.",
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: "Search Agent",
instructions: "Search the documentation index to answer questions.",
tools: [new AzureAISearchToolDefinition()],
toolResources: new ToolResources { AzureAISearch = searchResource }
);
9. Limpeza
await client.Threads.DeleteThreadAsync(thread.Id);
await client.Administration.DeleteAgentAsync(agent.Id);
await client.VectorStores.DeleteVectorStoreAsync(vectorStore.Id);
await client.Files.DeleteFileAsync(file.Id);
Ferramentas Disponíveis
| Ferramenta | Classe | Finalidade |
|---|
| Interpretador de Código | CodeInterpreterToolDefinition | Executar código Python, gerar visualizações |
| Busca de Arquivos | FileSearchToolDefinition | Pesquisar arquivos enviados via vector stores |
| Chamada de Função | FunctionToolDefinition | Chamar funções personalizadas |
| Ancoragem no Bing | BingGroundingToolDefinition | Pesquisa na web via Bing |
| Azure AI Search | AzureAISearchToolDefinition | Pesquisar índices do Azure AI Search |
| OpenAPI | OpenApiToolDefinition | Chamar APIs externas via especificação OpenAPI |
| Azure Functions | AzureFunctionToolDefinition | Invocar Azure Functions |
| MCP | MCPToolDefinition | Ferramentas do Model Context Protocol |
| SharePoint | SharepointToolDefinition | Acessar conteúdo do SharePoint |
| Microsoft Fabric | MicrosoftFabricToolDefinition | Acessar dados do Fabric |
Tipos de Atualização de Streaming
| Tipo de Atualização | Descrição |
|---|
StreamingUpdateReason.RunCreated | Run iniciada |
StreamingUpdateReason.RunInProgress | Run em processamento |
StreamingUpdateReason.RunCompleted | Run concluída |
StreamingUpdateReason.RunFailed | Run com erro |
MessageContentUpdate | Fragmento de conteúdo de texto |
RunStepUpdate | Mudança de status da etapa |
Referência de Tipos Principais
| Tipo | Finalidade |
|---|
PersistentAgentsClient | Ponto de entrada principal |
PersistentAgent | Agente com modelo, instruções, ferramentas |
PersistentAgentThread | Thread de conversa |
PersistentThreadMessage | Mensagem em thread |
ThreadRun | Execução do agente contra a thread |
RunStatus | Em fila, Em andamento, Requer ação, Concluído, Falhou |
ToolResources | Recursos de ferramentas combinados |
ToolOutput | Resposta de chamada de função |
Melhores Práticas
- Sempre descartar clientes — Use instruções
using ou descarte explícito
- Fazer polling com atrasos apropriados — 500ms recomendado entre verificações de status
- Limpar recursos — Excluir threads e agentes quando terminar
- Lidar com todos os status de run — Verificar
RequiresAction, Failed, Cancelled
- Usar streaming para UX em tempo real — Melhor experiência do usuário que polling
- Armazenar IDs, não objetos — Referenciar agentes/threads por ID
- Usar métodos assíncronos — Todas as operações devem ser assíncronas
Tratamento de Erros
using Azure;
try
{
var agent = await client.Administration.CreateAgentAsync(...);
}
catch (RequestFailedException ex) when (ex.Status == 404)
{
Console.WriteLine("Recurso não encontrado");
}
catch (RequestFailedException ex)
{
Console.WriteLine($"Erro: {ex.Status} - {ex.ErrorCode}: {ex.Message}");
}
SDKs Relacionados
| SDK | Finalidade | Instalação |
|---|
Azure.AI.Agents.Persistent | Agentes de baixo nível (este SDK) | dotnet add package Azure.AI.Agents.Persistent |
Azure.AI.Projects | Cliente de projeto de alto nível | dotnet add package Azure.AI.Projects |
Links de Referência