Azure AI Agents Persistent SDK for .NET. Low-level SDK for creating and managing AI agents with threads, messages, runs, and tools.
npx skills add https://github.com/lingxling/awesome-skills-cn --skill azure-ai-agents-persistent-dotnet
Low-level SDK for creating and managing persistent AI agents with threads, messages, runs, and tools.
dotnet add package Azure.AI.Agents.Persistent --prerelease
dotnet add package Azure.Identity
Current Versions: Stable v1.1.0, Preview v1.2.0-beta.8
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>
using Azure.AI.Agents.Persistent;
using Azure.Identity;
var projectEndpoint = Environment.GetEnvironmentVariable("PROJECT_ENDPOINT");
PersistentAgentsClient client = new(projectEndpoint, new DefaultAzureCredential());
PersistentAgentsClient
├── Administration → Agent CRUD operations
├── Threads → Thread management
├── Messages → Message operations
├── Runs → Run execution and streaming
├── Files → File upload/download
└── VectorStores → Vector store management
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()]
);
// Create thread
PersistentAgentThread thread = await client.Threads.CreateThreadAsync();
// Create message
await client.Messages.CreateMessageAsync(
thread.Id,
MessageRole.User,
"I need to solve the equation `3x + 11 = 14`. Can you help me?"
);
// Create run
ThreadRun run = await client.Runs.CreateRunAsync(
thread.Id,
agent.Id,
additionalInstructions: "Please address the user as Jane Doe."
);
// Poll for completion
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);
// Retrieve messages
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);
}
}
AsyncCollectionResult<StreamingUpdate> stream = client.Runs.CreateRunStreamingAsync(
thread.Id,
agent.Id
);
await foreach (StreamingUpdate update in stream)
{
if (update.UpdateKind == StreamingUpdateReason.RunCreated)
{
Console.WriteLine("--- Run started! ---");
}
else if (update is MessageContentUpdate contentUpdate)
{
Console.Write(contentUpdate.Text);
}
else if (update.UpdateKind == StreamingUpdateReason.RunCompleted)
{
Console.WriteLine("\n--- Run completed! ---");
}
}
// Define function tool
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 })
);
// Create agent with function
PersistentAgent agent = await client.Administration.CreateAgentAsync(
model: modelDeploymentName,
name: "Weather Bot",
instructions: "You are a weather bot.",
tools: [weatherTool]
);
// Handle function calls during polling
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)
{
// Execute function and get result
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);
// Upload file
PersistentAgentFileInfo file = await client.Files.UploadFileAsync(
filePath: "document.txt",
purpose: PersistentAgentFilePurpose.Agents
);
// Create vector store
PersistentAgentsVectorStore vectorStore = await client.VectorStores.CreateVectorStoreAsync(
fileIds: [file.Id],
name: "my_vector_store"
);
// Create file search resource
FileSearchToolResource fileSearchResource = new();
fileSearchResource.VectorStoreIds.Add(vectorStore.Id);
// Create agent with file search
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 }
);
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]
);
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 }
);
await client.Threads.DeleteThreadAsync(thread.Id);
await client.Administration.DeleteAgentAsync(agent.Id);
await client.VectorStores.DeleteVectorStoreAsync(vectorStore.Id);
await client.Files.DeleteFileAsync(file.Id);
| Tool | Class | Purpose |
|------|-------|---------|
| Code Interpreter | CodeInterpreterToolDefinition | Execute Python code, generate visualizations |
| File Search | FileSearchToolDefinition | Search uploaded files via vector stores |
| Function Calling | FunctionToolDefinition | Call custom functions |
| Bing Grounding | BingGroundingToolDefinition | Web search via Bing |
| Azure AI Search | AzureAISearchToolDefinition | Search Azure AI Search indexes |
| OpenAPI | OpenApiToolDefinition | Call external APIs via OpenAPI spec |
| Azure Functions | AzureFunctionToolDefinition | Invoke Azure Functions |
| MCP | MCPToolDefinition | Model Context Protocol tools |
| SharePoint | SharepointToolDefinition | Access SharePoint content |
| Microsoft Fabric | MicrosoftFabricToolDefinition | Access Fabric data |
| Update Type | Description |
|-------------|-------------|
| StreamingUpdateReason.RunCreated | Run started |
| StreamingUpdateReason.RunInProgress | Run processing |
| StreamingUpdateReason.RunCompleted | Run finished |
| StreamingUpdateReason.RunFailed | Run errored |
| MessageContentUpdate | Text content chunk |
| RunStepUpdate | Step status change |
| Type | Purpose |
|------|---------|
| PersistentAgentsClient | Main entry point |
| PersistentAgent | Agent with model, instructions, tools |
| PersistentAgentThread | Conversation thread |
| PersistentThreadMessage | Message in thread |
| ThreadRun | Execution of agent against thread |
| RunStatus | Queued, InProgress, RequiresAction, Completed, Failed |
| ToolResources | Combined tool resources |
| ToolOutput | Function call response |
using statements or explicit disposalRequiresAction, Failed, Cancelledusing Azure;
try
{
var agent = await client.Administration.CreateAgentAsync(...);
}
catch (RequestFailedException ex) when (ex.Status == 404)
{
Console.WriteLine("Resource not found");
}
catch (RequestFailedException ex)
{
Console.WriteLine($"Error: {ex.Status} - {ex.ErrorCode}: {ex.Message}");
}
| SDK | Purpose | Install |
|-----|---------|---------|
| Azure.AI.Agents.Persistent | Low-level agents (this SDK) | dotnet add package Azure.AI.Agents.Persistent |
| Azure.AI.Projects | High-level project client | dotnet add package Azure.AI.Projects |
| Resource | URL |
|----------|-----|
| NuGet Package | https://www.nuget.org/packages/Azure.AI.Agents.Persistent |
| API Reference | https://learn.microsoft.com/dotnet/api/azure.ai.agents.persistent |
| GitHub Source | https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/ai/Azure.AI.Agents.Persistent |
| Samples | https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/ai/Azure.AI.Agents.Persistent/samples |
This skill is applicable to execute the workflow or actions described in the overview.
Automate creating a GitHub repository and deploying a web project to Vercel. Use when the user asks to deploy a website/app to production, publish a project, or set up GitHub + Vercel deployment.
Deploy applications and websites to Vercel. Use this skill when the user requests deployment actions such as "Deploy my app", "Deploy this to production", "Create a preview deployment", "Deploy and give me the link", or "Push this live". No authentication required - returns preview URL and claimable deployment link.
Assess Kubernetes workloads and cluster configuration for AKS Automatic compatibility. Identifies incompatibilities, generates fixes, and guides migration from AKS Standard to AKS Automatic. WHEN: migrate to AKS Automatic, check AKS Automatic readiness, validate manifests for Automatic, assess cluster for Automatic compatibility, fix deployment for Automatic compatibility, identify AKS Automatic migration blockers, is my cluster ready for AKS Automatic.
Discovers available Azure OpenAI model capacity across regions and projects. Analyzes quota limits, compares availability, and recommends optimal deployment locations based on capacity requirements. USE FOR: find capacity, check quota, where can I deploy, capacity discovery, best region for capacity, multi-project capacity search, quota analysis, model availability, region comparison, check TPM availability. DO NOT USE FOR: actual deployment (hand off to preset or customize after discovery), quota increase requests (direct user to Azure Portal), listing existing deployments.
Interactive guided deployment flow for Azure OpenAI models with full customization control. Step-by-step selection of model version, SKU (GlobalStandard/Standard/ProvisionedManaged), capacity, RAI policy (content filter), and advanced options (dynamic quota, priority processing, spillover). USE FOR: custom deployment, customize model deployment, choose version, select SKU, set capacity, configure content filter, RAI policy, deployment options, detailed deployment, advanced deployment, PTU deployment, provisioned throughput. DO NOT USE FOR: quick deployment to optimal region (use preset).
Unified Azure OpenAI model deployment skill with intelligent intent-based routing. Handles quick preset deployments, fully customized deployments (version/SKU/capacity/RAI policy), and capacity discovery across regions and projects. USE FOR: deploy model, deploy gpt, create deployment, model deployment, deploy openai model, set up model, provision model, find capacity, check model availability, where can I deploy, best region for model, capacity analysis. DO NOT USE FOR: listing existing deployments (use foundry_models_deployments_list MCP tool), deleting deployments, agent creation (use agent/create), project creation (use project/create).
Intelligently deploys Azure OpenAI models to optimal regions by analyzing capacity across all available regions. Automatically checks current region first and shows alternatives if needed. USE FOR: quick deployment, optimal region, best region, automatic region selection, fast setup, multi-region capacity check, high availability deployment, deploy to best location. DO NOT USE FOR: custom SKU selection (use customize), specific version selection (use customize), custom capacity configuration (use customize), PTU deployments (use customize).
This skill should be used when working with LaminDB, an open-source data framework for biology that makes data queryable, traceable, reproducible, and FAIR. Use when managing biological datasets (scRNA-seq, spatial, flow cytometry, etc.), tracking computational workflows, curating and validating data with biological ontologies, building data lakehouses, or ensuring data lineage and reproducibility in biological research. Covers data management, annotation, ontologies (genes, cell types, diseases, tissues), schema validation, integrations with workflow managers (Nextflow, Snakemake) and MLOps platforms (W&B, MLflow), and deployment strategies.
Take lingxling/azure-ai-agents-persistent-dotnet from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.