From 1cc9d8ecb720768961aea49fb1e117346d15b5d4 Mon Sep 17 00:00:00 2001 From: Yogesh Rao Date: Tue, 19 May 2026 11:52:12 +0530 Subject: [PATCH] feat: improve azure-ai-projects-dotnet skill score MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hey @thegovind 👋 I ran your skills through `tessl skill review` at work and found some targeted improvements for the `azure-ai-projects-dotnet` skill. Here's the before/after: | Skill | Before | After | Change | |-------|--------|-------|--------| | azure-ai-projects-dotnet | 86% | 90% | +4% |
Changes summary **azure-ai-projects-dotnet (86% → 90%)**: - Fixed frontmatter description format from literal block (`|`) to standard quoted string - Added validation checkpoints to evaluation workflow — polling for completion status and failure detection before proceeding - Added verification step after dataset upload to confirm success - Added confirmation output after index creation - Removed redundant "Key Types Reference" table (all types already visible in Client Hierarchy diagram and code examples) - Removed redundant "Related SDKs" table (duplicated the Installation section) - Removed generic "Error Handling" section — consolidated the `RequestFailedException` pattern into Best Practices as a single actionable line - Trimmed Best Practices to 5 high-value, Azure AI Projects-specific items with reasoning (removed generic Azure SDK advice Claude already knows) - Tightened authentication section by removing inline comments that restated what the code shows - Cleaned up environment variable annotations for consistency Net result: 27 lines added, 64 removed — tighter, more actionable, with proper workflow validation patterns.
**Note:** I noticed the plugin skills are synced from GitHub-Copilot-for-Azure — if these improvements look good, it might be worth applying similar patterns to the sync source so they carry forward on the next sync. I also stress-tested your `azure-ai-projects-dotnet` skill against a few real-world task evals and it held up really well on versioned agent creation with web search tools and evaluation orchestration with status polling. Kudos for that. Honest disclosure — I work at @tesslio where we build tooling around skills like these. Not a pitch — just saw room for improvement and wanted to contribute. Want to self-improve your skills? Just point your agent (Claude Code, Codex, etc.) at [this Tessl guide](https://docs.tessl.io/evaluate/optimize-a-skill-using-best-practices) and ask it to optimize your skill. Ping me — [@yogesh-tessl](https://github.com/yogesh-tessl) — if you hit any snags. Thanks in advance 🙏 --- .../skills/azure-ai-projects-dotnet/SKILL.md | 91 ++++++------------- 1 file changed, 27 insertions(+), 64 deletions(-) diff --git a/.github/plugins/azure-sdk-dotnet/skills/azure-ai-projects-dotnet/SKILL.md b/.github/plugins/azure-sdk-dotnet/skills/azure-ai-projects-dotnet/SKILL.md index 80428335..5cc04f1d 100644 --- a/.github/plugins/azure-sdk-dotnet/skills/azure-ai-projects-dotnet/SKILL.md +++ b/.github/plugins/azure-sdk-dotnet/skills/azure-ai-projects-dotnet/SKILL.md @@ -1,7 +1,6 @@ --- name: azure-ai-projects-dotnet -description: | - Azure AI Projects SDK for .NET. High-level client for Azure AI Foundry projects including agents, connections, datasets, deployments, evaluations, and indexes. Use for AI Foundry project management, versioned agents, and orchestration. Triggers: "AI Projects", "AIProjectClient", "Foundry project", "versioned agents", "evaluations", "datasets", "connections", "deployments .NET". +description: "Azure AI Projects SDK for .NET. High-level client for Azure AI Foundry projects including agents, connections, datasets, deployments, evaluations, and indexes. Use for AI Foundry project management, versioned agents, and orchestration. Triggers: AI Projects, AIProjectClient, Foundry project, versioned agents, evaluations, datasets, connections, deployments .NET." license: MIT metadata: author: Microsoft @@ -31,11 +30,11 @@ dotnet add package Azure.AI.Agents.Persistent --prerelease ## Environment Variables ```bash -PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ # Required: Azure AI project endpoint -MODEL_DEPLOYMENT_NAME=gpt-4o-mini # Required: model deployment name -CONNECTION_NAME= # Optional: project connection name -AI_SEARCH_CONNECTION_NAME= # Optional: Azure AI Search connection name -AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production +PROJECT_ENDPOINT=https://.services.ai.azure.com/api/projects/ +MODEL_DEPLOYMENT_NAME=gpt-4o-mini +CONNECTION_NAME= # optional +AI_SEARCH_CONNECTION_NAME= # optional +AZURE_TOKEN_CREDENTIALS=prod # optional, for production credential selection ``` ## Authentication @@ -45,16 +44,10 @@ using Azure.Identity; using Azure.AI.Projects; var endpoint = Environment.GetEnvironmentVariable("PROJECT_ENDPOINT"); -// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS= var credential = new DefaultAzureCredential( DefaultAzureCredential.DefaultEnvironmentVariableName ); -// Or use a specific credential directly in production: -// See https://learn.microsoft.com/dotnet/api/overview/azure/identity-readme?view=azure-dotnet#credential-classes -// var credential = new ManagedIdentityCredential(); -AIProjectClient projectClient = new AIProjectClient( - new Uri(endpoint), - credential); +AIProjectClient projectClient = new AIProjectClient(new Uri(endpoint), credential); ``` ## Client Hierarchy @@ -198,6 +191,10 @@ FileDataset fileDataset = projectClient.Datasets.UploadFile( filePath: "data/training.txt", connectionName: connectionName); +// Verify upload succeeded +AIProjectDataset uploaded = projectClient.Datasets.GetDataset("my-dataset", "1.0"); +Console.WriteLine($"Dataset uploaded: {uploaded.Name} v{uploaded.Version}"); + // Upload folder FolderDataset folderDataset = projectClient.Datasets.UploadFolder( name: "my-dataset", @@ -206,9 +203,6 @@ FolderDataset folderDataset = projectClient.Datasets.UploadFolder( connectionName: connectionName, filePattern: new Regex(".*\\.txt")); -// Get dataset -AIProjectDataset dataset = projectClient.Datasets.GetDataset("my-dataset", "1.0"); - // Delete dataset projectClient.Datasets.Delete("my-dataset", "1.0"); ``` @@ -227,6 +221,8 @@ searchIndex = (AzureAISearchIndex)projectClient.Indexes.CreateOrUpdate( version: "1.0", index: searchIndex); +Console.WriteLine($"Index created: {searchIndex.Name} (connection: {searchIndex.IndexConnectionName})"); + // List indexes foreach (AIProjectIndex index in projectClient.Indexes.GetIndexes()) { @@ -259,8 +255,15 @@ Evaluation evaluation = new Evaluation( // Run evaluation Evaluation result = projectClient.Evaluations.Create(evaluation: evaluation); -// Get evaluation -Evaluation getResult = projectClient.Evaluations.Get(result.Name); +// Poll until evaluation completes +while (result.Status != EvaluationStatus.Completed && result.Status != EvaluationStatus.Failed) +{ + await Task.Delay(2000); + result = projectClient.Evaluations.Get(result.Name); +} + +if (result.Status == EvaluationStatus.Failed) + throw new InvalidOperationException($"Evaluation failed: {result.Name}"); // List evaluations foreach (var eval in projectClient.Evaluations.GetAll()) @@ -302,53 +305,13 @@ Console.WriteLine(result.Content[0].Text); | Azure Functions | `AzureFunctionToolDefinition` | Invoke Azure Functions | | MCP | `MCPToolDefinition` | Model Context Protocol tools | -## Key Types Reference - -| Type | Purpose | -|------|---------| -| `AIProjectClient` | Main entry point | -| `PersistentAgentsClient` | Low-level agent operations | -| `PromptAgentDefinition` | Versioned agent definition | -| `AgentVersion` | Versioned agent instance | -| `AIProjectConnection` | Connection to Azure resource | -| `AIProjectDeployment` | Model deployment info | -| `AIProjectDataset` | Dataset metadata | -| `AIProjectIndex` | Search index metadata | -| `Evaluation` | Evaluation configuration and results | - ## Best Practices -1. **Use `DefaultAzureCredential`** for production authentication -2. **Use async methods** (`*Async`) for all I/O operations -3. **Poll with appropriate delays** (500ms recommended) when waiting for runs -4. **Clean up resources** — delete threads, agents, and files when done -5. **Use versioned agents** (via `Azure.AI.Projects.OpenAI`) for production scenarios -6. **Store connection IDs** rather than names for tool configurations -7. **Use `includeCredentials: true`** only when credentials are needed -8. **Handle pagination** — use `AsyncPageable` for listing operations - -## Error Handling - -```csharp -using Azure; - -try -{ - var result = await projectClient.Evaluations.CreateAsync(evaluation); -} -catch (RequestFailedException ex) -{ - Console.WriteLine($"Error: {ex.Status} - {ex.ErrorCode}: {ex.Message}"); -} -``` - -## Related SDKs - -| SDK | Purpose | Install | -|-----|---------|---------| -| `Azure.AI.Projects` | High-level project client (this SDK) | `dotnet add package Azure.AI.Projects` | -| `Azure.AI.Agents.Persistent` | Low-level agent operations | `dotnet add package Azure.AI.Agents.Persistent` | -| `Azure.AI.Projects.OpenAI` | Versioned agents with OpenAI | `dotnet add package Azure.AI.Projects.OpenAI` | +1. **Use versioned agents** (via `Azure.AI.Projects.OpenAI`) for production scenarios — they support rollback and A/B testing +2. **Store connection IDs** rather than names for tool configurations — names can change, IDs are stable +3. **Use `includeCredentials: true`** only when credentials are needed — reduces exposure surface +4. **Poll with appropriate delays** (500ms for agent runs, 2s for evaluations) when waiting for async operations +5. **All Azure SDK calls throw `RequestFailedException`** on failure — catch it to inspect `Status`, `ErrorCode`, and `Message` ## Reference Links