GitHub Copilot ChatGPT Claude Codex CLI Cursor opencode Skill Text

skill-creator

Guide for creating effective skills for AI coding agents working with Azure SDKs and Microsoft Foundry services. Use when creating new skills or updating existing skills.

Ciza · 0 points · 20 views 1 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download microsoft-skills-.github_skills_skill-creator-e58528d.zip · 40 KB
Part of microsoft/skills — 195 skills

Install

skills CLI npx skills add https://github.com/microsoft/skills/tree/main/.github/skills/skill-creator
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
Git git clone https://github.com/microsoft/skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Skill Creator

Guide for creating skills that extend AI agent capabilities, with emphasis on Azure SDKs and Microsoft Foundry.

Required Context: When creating SDK or API skills, users MUST provide the SDK package name, documentation URL, or repository reference for the skill to be based on.

About Skills

Skills are modular knowledge packages that transform general-purpose agents into specialized experts:

  1. Procedural knowledge — Multi-step workflows for specific domains
  2. SDK expertise — API patterns, authentication, error handling for Azure services
  3. Domain context — Schemas, business logic, company-specific patterns
  4. Bundled resources — Scripts, references, templates for complex tasks

Core Principles

1. Concise is Key

The context window is a shared resource. Challenge each piece: "Does this justify its token cost?"

For domain/procedural skills: Agents are already capable. Only add what they don't already know.

For SDK/API skills: Users MUST provide SDK package name, documentation URL, or repository reference. The skill cannot be created without this context.

2. Fresh Documentation First

Azure SDKs change constantly. Skills should instruct agents to verify documentation:

## Before Implementation

Search `microsoft-docs` MCP for current API patterns:

- Query: "[SDK name] [operation] python"
- Verify: Parameters match your installed SDK version

3. Degrees of Freedom

Match specificity to implementation constraints. High freedom when approaches vary; low freedom when precise execution is required:

Freedom When Example
High Multiple valid approaches Text guidelines
Medium Preferred pattern with variation Pseudocode
Low Must be exact Specific scripts

4. Progressive Disclosure

Skills load in three levels:

  1. Metadata (~100 words) — Always in context
  2. SKILL.md body (<5k words) — When skill triggers
  3. References (unlimited) — As needed

Keep SKILL.md under 500 lines. Split into reference files when approaching this limit.


Skill Structure

Quick reference:

skill-name/
├── SKILL.md (required)
│   ├── YAML frontmatter (name, description)
│   └── Markdown instructions
└── Bundled Resources (optional)
    ├── scripts/      — Executable code
    ├── references/   — Documentation loaded as needed
    └── assets/       — Output resources (templates, images)

For Azure SDK skills, follow the Skill Section Order below. For domain skills, use your judgment to organize logically.

SKILL.md Essentials

  • Frontmatter: name and description (description triggers the skill)
  • Body: Keep under 500 lines; split large skills into reference files

Bundled Resources (Optional)

Type When to Include Examples
scripts/ Reused code patterns Auth setup, CLI scripts
references/ Feature deep-dives and overflow examples capabilities.md index, non-hero-scenarios.md, API docs
assets/ Output templates Boilerplate code, images

Creating Azure SDK Skills

When creating skills for Azure SDKs, follow these patterns consistently.

Token Budget Guidelines (REQUIRED)

Every Azure SDK skill MUST stay within these token limits:

Section Target Absolute Max
Installation + Env Vars 100 tokens 150
Authentication & Lifecycle 200 tokens 300
Core Workflow (1 example) 300 tokens 400
Feature Tables 200 tokens 300
Best Practices (6-8 items) 200 tokens 250
References (reference/ links) 100 tokens 150
Total SKILL.md ~1100 tokens ~1500 tokens

Enforcement:

  • Exceeding max limit → refactor into /references/ subdirectories
  • When approaching 500 lines → move entire sections to reference files
  • Annotate with <!-- Token Count: ~XXXX (target: 1100, max: 1500) --> immediately below the skill's H1

Reference Extraction Guide (REQUIRED)

Decide what goes in SKILL.md vs. /references/ using these signals:

Signal Move to /references/ Keep in SKILL.md
Use frequency <20% of typical use ~80%+ of workflows
Cognitive load Advanced patterns, multiple options Single happy path
Example length >10 lines, multiple paths 1-5 lines, single path

Content extraction rules:

  • Batch operations → /references/batch-operations.md
  • Error handling (beyond try-except) → /references/error-handling.md
  • Performance tuning → /references/performance.md
  • Alternative workflows → /references/workflows-comparison.md
  • Streaming/events → /references/streaming.md
  • Advanced auth → /references/auth-strategies.md
  • Tool integration → /references/tools.md
  • Breaking changes → /references/migration.md

Decision: Keep common case in SKILL.md, move edge cases to /references/.


Core Workflow Discipline (REQUIRED)

Every Azure SDK skill must clarify which workflow(s) it documents.

Case 1: Single clear "core workflow" (majority of services)

If one pattern handles ~80% of use cases:

  1. Designate it as the core workflow
  2. Show ONLY this workflow in SKILL.md (one complete, runnable example)
  3. Defer alternatives to /references/:
    • Batch operations → /references/batch-operations.md
    • Error handling → /references/error-handling.md
    • Performance tuning → /references/performance.md
    • Alternative workflows → /references/workflows-comparison.md

Example: Azure Key Vault Secrets (core workflow: retrieve a secret using managed identity). Alternative authentication workflows in /references/: local development with DefaultAzureCredential, workload identity, and service-principal credentials (client secret or certificate).

Case 2: Multiple equally-valid "core workflows" (e.g., authentication strategies, deployment targets)

If no single pattern dominates:

  1. Include every hero scenario in SKILL.md, even when that means multiple equally valid workflows
  2. Show one complete, runnable example for each hero scenario in SKILL.md
  3. Use /references/workflows-comparison.md for trade-offs, secondary variations, and deeper context that would otherwise bloat the main file
  4. Do NOT treat valid alternatives as "advanced" when they are core to real usage — they're equally valid, just different contexts

Example: Azure Identity SDK has several hero scenarios. Keep the primary local-development and production-safe credential flows in SKILL.md, then use /references/credential-types.md for deeper comparisons across AzureCliCredential, workload identity, service principal variants, and other secondary credential choices.

Decision rule: If you're unsure, ask: "Would a user choosing the other approach call what I wrote wrong?" If yes, it's another hero scenario and belongs in SKILL.md. If no, it can be summarized and linked from /references/.


Skill Section Order

Follow this structure (based on existing Azure SDK skills):

  1. Title — # SDK Name
  2. Installation — pip install, npm install, etc.
  3. Environment Variables — Required configuration, with an inline comment explaining when it's required. If using DefaultAzureCredential in production, include AZURE_TOKEN_CREDENTIALS (set to prod or <specific_credential>)
  4. Authentication & Lifecycle — For Python skills, prefer DefaultAzureCredential: use it as-is for local development, and constrain it for production by setting AZURE_TOKEN_CREDENTIALS to prod (or a specific target credential name). A specific Microsoft Entra Token credential such as ManagedIdentityCredential or WorkloadIdentityCredential may be used directly instead. For Python skills, this section MUST start with the standard callout block (see Required Authentication & Lifecycle Callout (Python) below).
  5. Core Workflow — Minimal viable example (per core workflow discipline above)
  6. Feature Tables — Clients, methods, tools
  7. Best Practices — Numbered list
  8. Reference Links — Table linking to /references/*.md (for Azure SDK skills, include capabilities.md + non-hero-scenarios.md)

Required Authentication & Lifecycle Callout (Python)

Scope: Python skills (-py suffix) only. Other languages may follow their own idioms.

Every Python Azure SDK skill MUST open its ## Authentication & Lifecycle section with the following callout block, verbatim, before any code samples. This makes the two non-negotiable rules visible to users before they read or copy any client setup code.

## Authentication & Lifecycle

> **🔑 Two rules apply to every code sample below:**
>
> 1. **Prefer `DefaultAzureCredential` for local development.** It works as-is with Azure CLI / VS Code / Developer CLI. For production, either constrain `DefaultAzureCredential` to production-safe credentials or use a specific credential directly. Avoid connection strings, account/API keys — they bypass Entra audit and rotation.
>    - Local dev: `DefaultAzureCredential` works as-is.
>    - Production: set `AZURE_TOKEN_CREDENTIALS=prod` (or `AZURE_TOKEN_CREDENTIALS=<specific_credential>`) to constrain the credential chain to production-safe credentials.
> 2. **Wrap every client in a context manager** so HTTP transports, sockets, and token caches are released deterministically:
>    - Sync: `with <Client>(...) as client:`
>    - Async: `async with <Client>(...) as client:` **and** `async with DefaultAzureCredential() as credential:` (from `azure.identity.aio`)
>
> Snippets may abbreviate this setup, but production code should always follow both rules.

Placement rules:

  • Insert immediately under the ## Authentication & Lifecycle heading, before the first code sample.
  • Do not paraphrase or restructure the wording — the consistency across skills is the point.
  • If the SDK does not support Entra ID at all (rare — e.g. some legacy speech REST endpoints, websocket APIs that require subscription keys), keep rule #2 (context managers) and replace rule #1 with a single sentence noting the SDK requires API-key auth and explaining why Entra is not yet available.
  • If the SDK is async-only (e.g. azure-ai-voicelive), keep both rules but show only the async form in the bullets.
  • Skip the callout entirely for non-Azure Python skills with no client lifecycle (e.g. pydantic-models-py).

Code sample enforcement. Every client construction in the skill body must demonstrate both rules:

  • Show with / async with on every client instantiation in usage examples (not just the auth section).
  • Show DefaultAzureCredential in the primary auth example. Do not delete API-key examples for SDKs where keys are still officially supported — many existing users (especially in regulated environments still completing their Entra rollout) need a copy-pastable working sample. Demote the keyed snippet into a clearly-labeled ### Legacy: API Key (existing keyed deployments) subsection placed after the primary DefaultAzureCredential block in the same ## Authentication & Lifecycle section. Include a one-line note that new code should use DefaultAzureCredential and that the keyed path is for existing deployments. Also add the <SERVICE>_KEY env var back to the Environment Variables block with a # Only required for the legacy API-key auth path below comment.
  • A handful of services have key-specific quirks worth calling out in the Legacy subsection (e.g. azure-ai-translation-text requires a region= parameter when using a key against the global endpoint, because token-credential auth requires a custom subdomain endpoint). Surface these in the demoted block rather than dropping the example.
  • For async examples, wrap DefaultAzureCredential from azure.identity.aio in async with credential: alongside the client.

Authentication Pattern (All Languages)

For local development, use DefaultAzureCredential which supports multiple auth methods. For production, use a specific credential type or configure DefaultAzureCredential with environment variable AZURE_TOKEN_CREDENTIALS set to prod or specify the target credential.

If configuring a Rust skill, use DeveloperToolsCredential for local development and ManagedIdentityCredential for production. The Rust SDK does not support DefaultAzureCredential, so explicitly use the appropriate credential in each environment.

# Python — note: client is wrapped in `with` for deterministic cleanup
from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
# Local dev: DefaultAzureCredential works as-is.
credential = DefaultAzureCredential()
# Production alternative: constrain DefaultAzureCredential with AZURE_TOKEN_CREDENTIALS.
# credential = DefaultAzureCredential(require_envvar=True)
# Or use a specific credential directly in production:
# See https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python#credential-classes
# credential = ManagedIdentityCredential()
with ServiceClient(endpoint, credential) as client:
    client.do_thing()
// C#
using Azure.Identity;

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
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();
var client = new ServiceClient(new Uri(endpoint), credential);
// Java
import com.azure.identity.AzureIdentityEnvVars;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.ManagedIdentityCredential;
import com.azure.identity.ManagedIdentityCredentialBuilder;

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
TokenCredential credential = new DefaultAzureCredentialBuilder()
    .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
    .build();
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes
// TokenCredential credential = new ManagedIdentityCredentialBuilder().build();
ServiceClient client = new ServiceClientBuilder()
    .endpoint(endpoint)
    .credential(credential)
    .buildClient();
// TypeScript
import {
  DefaultAzureCredential,
  ManagedIdentityCredential,
} from "@azure/identity";
// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
const credential = new DefaultAzureCredential({
  requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"],
});
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
// const credential = new ManagedIdentityCredential();
const client = new ServiceClient(endpoint, credential);
// Go
import (
  "context"

  "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
  "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
)

ctx := context.Background()

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
  panic(err)
}

// Or use a specific credential directly in production:
// cred, err := azidentity.NewManagedIdentityCredential(nil)

client, err := azblob.NewClient("https://<account>.blob.core.windows.net/", cred, nil)
if err != nil {
  panic(err)
}

_ = client
_ = ctx
// Rust
use azure_identity::DeveloperToolsCredential;
use azure_storage_blob::BlobServiceClient;

let credential = DeveloperToolsCredential::new(); // Local dev
let client = BlobServiceClient::new(
    "https://<account>.blob.core.windows.net/",
    credential,
    None,
)?;

Never hardcode credentials. Use environment variables.

Anti-Patterns: What NOT to Do (REQUIRED Reading)

These patterns cause bloat and inefficiency. Every skill author must review this section before writing.

Anti-Pattern 1: "Exhaustive API Reference"

  • ❌ Don't: List all 50 SDK methods in a feature table with code samples for every variant
  • ✅ Do: Show 3-5 core methods in a table; link to official Azure API reference for exhaustive list
  • Token cost: Listing all methods + examples = 400-600 tokens wasted
  • User impact: Overwhelming cognitive load; users don't know what to use

Anti-Pattern 2: "Multiple Ways to Solve One Problem"

  • ❌ Don't: "Here's approach A, B, C, and D to paginate results" in the main body
  • ✅ Do: "Use ItemPaged for sync pagination" (primary example); link alternatives to /references/
  • Token cost: Each alternate approach = 50-100 tokens; 5 approaches = skill becomes inefficient
  • User impact: Decision paralysis; users re-read everything

Anti-Pattern 3: "Beginner + Intermediate + Advanced in One Skill"

  • ❌ Don't: Skill that goes from "what is a client?" to "custom retry policies" to "circuit breaker patterns"
  • ✅ Do: Core workflow covers 80% use case; advanced patterns in /references/
  • Token cost: Every skill level adds 200-300 tokens; three levels = 600-900 extra tokens
  • User impact: Experts bored, beginners overwhelmed; nobody gets what they need

Anti-Pattern 4: "Restating Official Documentation"

  • ❌ Don't: "The CosmosClient constructor takes an endpoint (string) and credential (TokenCredential). The endpoint identifies the Azure Cosmos resource..."
  • ✅ Do: Show code: client = CosmosClient(endpoint, credential). Link to official docs: microsoft-docs MCP.
  • Token cost: Verbose explanation = 50-100 tokens per parameter; large APIs waste 300+ tokens
  • User impact: Redundant; official docs are authoritative, skill should show usage not repeat them

Anti-Pattern 5: "Verbose Explanation When Example Suffices"

  • ❌ Don't: "To create a client, you first instantiate the class using the constructor, passing the endpoint and credential parameters. The endpoint is a string that identifies your resource..."
  • ✅ Do: Show code immediately: with CosmosClient(endpoint, credential) as client:

Efficiency Validation (REQUIRED - Phase 2)

During authoring, validate skill efficiency manually, then run the Vally eval if the skill has one under tests/scenarios/<skill-name>/vally/.

1. Measure token count:

Use a token counter or model playground to measure each section. Compare to the Token Budget Guidelines targets above. If any section exceeds max, move content to /references/.

2. Run anti-pattern checklist:

  • No exhaustive API reference (show 3-5 core methods, not 50)
  • No multiple solutions to one problem in SKILL.md
  • No beginner+intermediate+advanced mixed
  • No restating official docs (code first, link to microsoft-docs)
  • No verbose prose (examples first, minimal text)

3. Example count audit:

  • 1 complete example per hero scenario / core workflow documented in SKILL.md. For Python SDKs that support both sync and async, the paired sync + async examples for the same workflow count as one workflow, not two.
  • Feature table includes 3-5 core methods (not comprehensive API)
  • Max 1 example per best practice bullet

4. Frontmatter validation:

  • name matches .github/skills/<name>/SKILL.md
  • description includes trigger keywords
  • description is concise (~200 chars is a good target; schema max is 1,024 chars)
  • If included, optional benchmark_tokens_* and benchmark_quality_* metadata fields are flat strings under metadata

4b. Authentication guidance validation (critical for all credentials):

  • If skill uses Azure Identity credentials, verify guidance against the current official credential docs for that language/package (Microsoft Learn where available; otherwise the upstream SDK repo or package docs)
  • For Python skills, development guidance may recommend DefaultAzureCredential (supports multiple dev credential types)
  • For Python skills, production guidance: DefaultAzureCredential alone (unconstrained) is not sufficient; require either AZURE_TOKEN_CREDENTIALS=prod (or a specific target credential) to constrain the chain, or a specific credential (e.g., ManagedIdentityCredential) used directly
  • For Rust skills, development/production guidance reflects the actual supported credentials (DeveloperToolsCredential for local dev; a specific production credential such as ManagedIdentityCredential for production)
  • Link to /references/auth-strategies.md or official docs for production credential selection

4c. Run Vally lint/eval (if the skill has a spec under tests/scenarios/<skill-name>/vally/):

# If the eval spec uses the shared Rust custom grader plugin, build it first.
(cd tests/scenarios/_shared/vally/grader-plugins/rust-cargo-build-failure && npm install && npm run build)

vally lint --eval-spec tests/scenarios/<skill-name>/vally/eval.yaml \
  --grader-plugin tests/scenarios/_shared/vally/grader-plugins/rust-cargo-build-failure \
  --strict

vally eval --eval-spec tests/scenarios/<skill-name>/vally/eval.yaml \
  --grader-plugin tests/scenarios/_shared/vally/grader-plugins/rust-cargo-build-failure
  • vally lint passes with no errors
  • vally eval passes (no error-severity findings) when COPILOT_TOKEN is available; otherwise lint-only is acceptable, matching the Vally Evaluation workflow behavior
  • Skills without a vally/ spec skip this step — it is optional per skill, not required for every skill

5. Spot check:

  • Can a user copy the core workflow and run it immediately?
  • Do all examples follow best practices (context managers, appropriate credentials)?
  • Are all environment variables documented?

Output: After validation, annotate the skill header with measured token count:

# Azure Service SDK

<!-- Token Count: ~1180 (target: 1100, max: 1500) -->

Standard Verb Patterns

Azure SDKs use consistent verbs across all languages:

Verb Behavior
create Create new; fail if exists
upsert Create or update
get Retrieve; error if missing
list Return collection
delete Succeed even if missing
begin Start long-running operation

Language-Specific Patterns

See references/azure-sdk-patterns.md for detailed patterns including:

  • Python: ItemPaged, LROPoller, context managers, Sphinx docstrings. When the SDK provides both sync and async clients, present both forms as first-class options; do not express a preference for either. When the SDK is sync-only or async-only, document the available mode only. Do not mix sync and async within a single code example. Always show with / async with context managers.
  • .NET: Response<T>, Pageable<T>, Operation<T>, mocking support
  • Java: Builder pattern, PagedIterable/PagedFlux, Reactor types
  • TypeScript: PagedAsyncIterableIterator, AbortSignal, browser considerations
  • Go: context.Context as first arg, runtime.Pager[T] via New*Pager() + More()/NextPage(ctx), runtime.Poller[T] via Begin* + PollUntilDone(ctx, nil), to.Ptr(...) helpers, and typed *azcore.ResponseError
  • Rust: Installation via cargo add, dependency rule for azure_core, Response<T>, Pager<T>, RequestContent::from(), .into_model(), explicit credential types, RBAC roles for Entra ID authentication

Required Best Practices in Every Skill (User-Facing)

Python, .NET, Java, TypeScript, and Go languages

These two rules are not just authoring conventions for the skill itself — they MUST be explicitly written into every generated skill's ## Best Practices section so end users who follow the skill apply them in their own code.

Add both items verbatim (adapted only for language/SDK specifics) as the first two items of the Best Practices list. Do not assume users will infer them from examples.

Standard wording (Python; adapt for other languages):

1. **Do not mix sync and async clients in the same call path.** Use either `azure.xxx` sync clients or `azure.xxx.aio` async clients within a single call path — do not combine both.
2. **Always use context managers for clients and async credentials.** Wrap every client in `with Client(...) as client:` (sync) or `async with Client(...) as client:` (async). For async `DefaultAzureCredential` from `azure.identity.aio`, also use `async with credential:` so tokens and transports are cleaned up.
3. **Use `DefaultAzureCredential`** for code that runs locally. For code that runs in Azure, either constrain `DefaultAzureCredential` with `AZURE_TOKEN_CREDENTIALS=prod` (or a specific target credential) or use a specific token credential directly (e.g. `ManagedIdentityCredential`, `WorkloadIdentityCredential`).

Variants to apply when the SDK shape differs:

Skill type Adjust item #1 to Adjust item #2 to
Async-only SDK (e.g. voicelive) "This SDK is async-only; use the .aio namespace throughout." keep standard
Framework guidance that is async-oriented (for example some agent frameworks) "Use the framework's documented async patterns where required, but do not claim async is globally preferred for Azure Python SDKs." keep standard
Provider-pattern (OpenTelemetry exporters/distro) keep standard "Call provider.shutdown() / flush() at process exit to flush telemetry — providers are not context managers."
REST-over-httpx skills keep standard "Use with httpx.Client(...) as client: (sync) or async with httpx.AsyncClient(...) as client: (async) so connections pool and close deterministically."
Identity skill keep standard "Use credentials as context managers (with DefaultAzureCredential() as credential:) when they own token caches / HTTP transports you want cleaned up; for async, use async with on credentials from azure.identity.aio."
FastAPI (non-Azure) "Pick def or async def per endpoint based on whether you call async I/O; do not mix sync and blocking calls in one handler." "Manage long-lived resources (DB pools, HTTP clients) in lifespan and inject via Depends; use with/async with for per-request resources."
Pure model/schema skill (no I/O, e.g. pydantic) skip both — not applicable skip

Enforcement in code examples. Every code example inside the skill must itself obey both rules, so the skill demonstrates what it prescribes:

  • Do not interleave sync and async calls within a single example. When the SDK provides both sync and async clients, show each mode in its own complete, self-contained example — a ### Sync subsection and an ### Async subsection — giving both equal prominence. When the SDK is sync-only or async-only, show only the available mode.
  • Every client instantiation in every example must be wrapped in with / async with. The only permitted exception is the mandatory Authentication snippet (which illustrates the credential + client construction pattern) and framework lifespan patterns where a client is owned by the app (e.g. FastAPI lifespan).
  • When async credentials from azure.identity.aio appear in an example, wrap them in async with credential: alongside the client.

Rust Language

These rules MUST be explicitly written into every Rust skill's ## Best Practices section as the first items:

  1. Use cargo add to manage dependencies, never edit Cargo.toml directly. Always use cargo add <crate> or cargo remove <crate> instead of manually modifying the manifest file. Official crates are published on crates.io and should be added via cargo.

  2. Add azure_core to Cargo.toml only when you import azure_core types directly. If your code imports types like azure_core::http::Url, azure_core::http::RequestContent, or azure_core::error::ErrorKind, explicitly add azure_core to your dependencies. If you only use types re-exported by service crates (e.g., via use azure_storage_blob::BlobClient), a direct azure_core dependency is optional.

  3. Use DeveloperToolsCredential for local development and ManagedIdentityCredential for production. The Rust SDK does not support DefaultAzureCredential, so explicitly use the appropriate credential in each environment.

  4. Use RequestContent::from() to wrap upload data. When uploading data (e.g., blobs), wrap the content in RequestContent::from(your_data) to ensure proper handling by the SDK.

  5. Assign appropriate RBAC roles for Entra ID auth. For production authentication using Entra ID, ensure the identity has the necessary RBAC role assigned (e.g., "Storage Blob Data Contributor" for blob write access).

  6. Always verify package versions using crates.io. Before using a package, check its version on crates.io to ensure you are using a stable and supported release.

  7. Future-proof #[non_exhaustive] model structs and enums. Azure Rust SDK request/response models are frequently #[non_exhaustive]. For externally constructible structs that also derive Default, end the initializer with ..Default::default() (even if every currently known field is set), suppressing the lint locally with #[allow(clippy::needless_update)] when needed. For truly #[non_exhaustive] structs (where Rust forbids external struct literals, producing E0639), use the provided constructor or builder, or construct a default value first and then mutate the fields you need. When matching an SDK enum, include a wildcard (_) arm so future service-added variants do not break the match. If a skill documents model construction, its code examples MUST demonstrate this pattern. See references/azure-sdk-patterns.md (Model Types) for the full example.

Example Effective Skills (Benchmark Only Structure-Compliant Skills)

Only benchmark Azure SDK skills that already use the required references/ layout (references/capabilities.md plus references/non-hero-scenarios.md). Older skills that predate that structure can still be useful for style ideas, but do not mirror them directly until they are brought into compliance.

A valid benchmark skill should:

  1. Stay at or under the 1,500-token absolute max (see Token Budget Guidelines above)
  2. Cover the hero workflow (CRUD or primary operations), not every feature variant
  3. Show 1-2 examples per concept, not 3-5
  4. Use tables for API summary (credential types, RBAC roles, client hierarchy)
  5. Link to official docs via microsoft-docs MCP instead of duplicating
  6. Move advanced patterns to /references/
  7. Include references/capabilities.md and references/non-hero-scenarios.md

Before writing your skill: Apply the checklist above directly, then mirror only the structure patterns that fit your use case.


Handling Deprecated or Rebranded SDKs

When an Azure SDK has been deprecated or rebranded, update skills to guide users toward the current package while maintaining backward compatibility:

1. Add a migration notice at the top of the skill:

> **⚠️ MIGRATION NOTICE**: The [Old Service Name] has been rebranded to **[New Service Name]**. While the package `old-package-name` remains available for compatibility, **new projects should use `new-package-name`** which provides the latest features and updates.
>
> **For new projects**: Use the `new-package-name` package instead.
>
> **This skill remains valid** for existing projects using `old-package-name`, but be aware you're using the legacy package name. The API patterns shown here are compatible with both packages.

2. Show both installation options:

## Installation

### Legacy Package (Old Name)

\`\`\`xml
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-old-package</artifactId>
<version>4.2.0</version>
</dependency>
\`\`\`

### Recommended Package (New Name)

**For new projects, use the rebranded package:**

\`\`\`xml
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-new-package</artifactId>
<version>1.0.0</version>
</dependency>
\`\`\`

> **Note**: The API patterns in this skill apply to both packages. Replace package names and imports as needed when using `azure-new-package`.

3. When to create a new skill vs. update existing:

  • Update existing skill if the API is largely compatible (same or similar class/method names)
  • Create new skill + migration guide if the API changed significantly (use references/migration.md)
  • Always cross-reference between old and new skills

Examples:

  • azure-ai-formrecognizer-java → azure-ai-documentintelligence (rebranded service)
  • azure-communication-callingserver-java → azure-communication-callautomation (deprecated, with migration guide)

Example: Azure SDK Skill Structure

---
name: skill-creator
description: |
  Azure AI Example SDK for Python. Use for [specific service features].
  Triggers: "example service", "create example", "list examples".
---

# Azure AI Example SDK

## Installation

\`\`\`bash
pip install azure-ai-example
\`\`\`

## Environment Variables

\`\`\`bash
AZURE_EXAMPLE_ENDPOINT=https://<resource>.example.azure.com
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
\`\`\`

## Authentication & Lifecycle

> **🔑 Two rules apply to every code sample below:**
>
> 1. **Prefer `DefaultAzureCredential` for local development.** It works as-is with Azure CLI / VS Code / Developer CLI. For production, either constrain `DefaultAzureCredential` to production-safe credentials or use a specific credential directly. Avoid connection strings, account/API keys — they bypass Entra audit and rotation.
>    - Local dev: `DefaultAzureCredential` works as-is.
>    - Production: set `AZURE_TOKEN_CREDENTIALS=prod` (or `AZURE_TOKEN_CREDENTIALS=<specific_credential>`) to constrain the credential chain to production-safe credentials.
> 2. **Wrap every client in a context manager** so HTTP transports, sockets, and token caches are released deterministically:
>    - Sync: `with <Client>(...) as client:`
>    - Async: `async with <Client>(...) as client:` **and** `async with DefaultAzureCredential() as credential:` (from `azure.identity.aio`)
>
> Snippets may abbreviate this setup, but production code should always follow both rules.

\`\`\`python
from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
from azure.ai.example import ExampleClient

# Local dev: DefaultAzureCredential works as-is.
credential = DefaultAzureCredential()

# Production alternative: constrain DefaultAzureCredential with AZURE_TOKEN_CREDENTIALS.
# credential = DefaultAzureCredential(require_envvar=True)

# Or use a specific credential directly in production:

# See https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python#credential-classes

# credential = ManagedIdentityCredential()

with ExampleClient(
endpoint=os.environ["AZURE_EXAMPLE_ENDPOINT"],
credential=credential,
) as client:
item = client.get_item("example")
\`\`\`

## Core Workflow

\`\`\`python
with ExampleClient(endpoint=endpoint, credential=credential) as client: # Create
item = client.create_item(name="example", data={...})

    # List (pagination handled automatically)
    for item in client.list_items():
        print(item.name)

    # Long-running operation
    poller = client.begin_process(item.id)
    result = poller.result()

    # Cleanup
    client.delete_item(item.id)

\`\`\`

## Reference Files

| File                                                                 | Contents                                               |
| -------------------------------------------------------------------- | ------------------------------------------------------ |
| [references/capabilities.md](references/capabilities.md)             | Capability index (hero coverage + links to deep-dives) |
| [references/non-hero-scenarios.md](references/non-hero-scenarios.md) | Concrete non-hero examples                             |
| [references/tools.md](references/tools.md)                           | Tool integrations                                      |
| [references/streaming.md](references/streaming.md)                   | Event streaming patterns                               |

Skill Creation Process

  1. Gather SDK Context — User provides SDK/API reference (REQUIRED)
  2. Understand — Research SDK patterns from official docs
  3. Plan — Identify reusable resources and product area category
  4. Create — Write SKILL.md in .github/skills/<skill-name>/
  5. Categorize — Create symlink in skills/<language>/<category>/
  6. Test — Create acceptance criteria and test scenarios
  7. Document — Update README.md skill catalog
  8. Iterate — Refine based on real usage

Step 1: Gather SDK Context (REQUIRED)

Before creating any SDK skill, the user MUST provide:

Required Example Purpose
SDK Package azure-ai-agents, Azure.AI.OpenAI, azblob Identifies the exact SDK
Documentation URL https://learn.microsoft.com/en-us/azure/ai-services/... Primary source of truth
Repository (optional) Azure/azure-sdk-for-python, Azure/azure-sdk-for-go For code patterns

Prompt the user if not provided:

To create this skill, I need:
1. The SDK package name (e.g., azure-ai-projects)
2. The Microsoft Learn documentation URL or GitHub repo
3. The target language (py/dotnet/ts/java/go)

Search official docs first:

# Use microsoft-docs MCP to get current API patterns
# Query: "[SDK name] [operation] [language]"
# Verify: Parameters match the latest SDK version

Step 2: Understand the Skill

Gather concrete examples:

  • "What SDK operations should this skill cover?"
  • "What triggers should activate this skill?"
  • "What errors do developers commonly encounter?"
Example Task Reusable Resource
Same auth code each time Code example in SKILL.md
Complex streaming patterns references/streaming.md
Tool configurations references/tools.md
Error handling patterns references/error-handling.md

Step 3: Plan Product Area Category

Skills are organized by language and product area in the skills/ directory via symlinks.

Product Area Categories:

Category Description Examples
foundry AI Foundry, agents, projects, inference azure-ai-agents-py, azure-ai-projects-py
data Storage, Cosmos DB, Tables, Data Lake azure-cosmos-py, azure-storage-blob-py
messaging Event Hubs, Service Bus, Event Grid azure-eventhub-py, azure-servicebus-py
monitoring OpenTelemetry, App Insights, Query azure-monitor-opentelemetry-py
identity Authentication, DefaultAzureCredential azure-identity-py
security Key Vault, secrets, keys, certificates azure-keyvault-py
integration API Management, App Configuration azure-appconfiguration-py
compute Batch, ML compute azure-compute-batch-java
container Container Registry, ACR azure-containerregistry-py

Determine the category based on:

  1. Azure service family (Storage → data, Event Hubs → messaging)
  2. Primary use case (AI agents → foundry)
  3. Existing skills in the same service area

Step 4: Create the Skill

Location: .github/skills/<skill-name>/SKILL.md

Naming convention:

  • azure-<service>-<subservice>-<language>
  • Examples: azure-ai-agents-py, azure-cosmos-java, azure-storage-blob-ts, azure-storage-blob-go
  • For Go skills in documentation prose, use the short package name (for example azblob).
  • Use the full module import path only in code/import examples (for example github.com/Azure/azure-sdk-for-go/sdk/storage/azblob).

For Azure SDK skills:

  1. Search microsoft-docs MCP for current API patterns
  2. Verify against installed SDK version
  3. Follow the section order above
  4. Include cleanup code in examples
  5. Add feature comparison tables

Write bundled resources first, then SKILL.md.

Quality assurance before finalizing:

  1. Measure section token counts as you write (use model playground token counter)
  2. Compare to Token Budget Guidelines targets
  3. Validate against anti-patterns checklist (see Anti-Patterns section)
  4. Extract to /references/ if section exceeds max tokens
  5. Run Efficiency Validation checklist, including vally lint/vally eval if the skill has a spec (see Efficiency Validation)
  6. Optionally add benchmark_tokens_* and benchmark_quality_* fields under the frontmatter's metadata mapping (flat string values)
  7. Add token count comment to skill header for future maintenance

Frontmatter (Enhanced with Benchmarking Metadata):

---
name: azure-service-py
description: |
  Azure Service SDK for Python. Use for [specific features].
  Triggers: "service name", "create resource", "specific operation".
metadata:
  benchmark_tokens_estimated: "1180"
  benchmark_tokens_target: "1100"
  benchmark_tokens_max: "1500"
  benchmark_quality_single_core_workflow: "true"
  benchmark_quality_examples_focused: "true"
  benchmark_quality_no_prose_bloat: "true"
  benchmark_quality_anti_patterns_checked: "true"
---

Metadata fields: (all values are strings, per the Agent Skills metadata spec — string keys mapped to string values)

  • benchmark_tokens_estimated — Actual measured token count
  • benchmark_tokens_target — Target efficiency (typically 1100)
  • benchmark_tokens_max — Absolute ceiling (1500; split if exceeded)
  • benchmark_quality_* — Individual anti-pattern checks, each a "true"/"false" string (e.g., benchmark_quality_single_core_workflow)

Step 5: Categorize with Symlinks

After creating the skill in .github/skills/, create a symlink in the appropriate category:

# Pattern: skills/<language>/<category>/<short-name> -> ../../../.github/skills/<full-skill-name>

# Example for azure-ai-agents-py in python/foundry:
cd skills/python/foundry
ln -s ../../../.github/skills/azure-ai-agents-py agents

# Example for azure-cosmos-db-py in python/data:
cd skills/python/data
ln -s ../../../.github/skills/azure-cosmos-db-py cosmos-db

# Example for azure-storage-blob-go in go/data:
cd skills/go/data
ln -s ../../../.github/skills/azure-storage-blob-go blob

Symlink naming:

  • Use short, descriptive names (e.g., agents, cosmos, blob)
  • Remove the azure- prefix and language suffix
  • Match existing patterns in the category

Verify the symlink:

ls -la skills/python/foundry/agents
# Should show: agents -> ../../../.github/skills/azure-ai-agents-py

Step 6: Create Tests

Every skill MUST have acceptance criteria and test scenarios.

6.1 Create Acceptance Criteria

Location: tests/scenarios/<skill-name>/acceptance-criteria.md

Keep acceptance criteria in the tests/ tree (never beside SKILL.md inside the skill folder).

Source materials (in priority order):

  1. Official Microsoft Learn docs (via microsoft-docs MCP)
  2. SDK source code from the repository
  3. Existing reference files in the skill

Format:

# Acceptance Criteria: <skill-name>

**SDK**: `package-name`
**Repository**: https://github.com/Azure/azure-sdk-for-<language>
**Purpose**: Skill testing acceptance criteria

---

## 1. Correct Import Patterns

### 1.1 Client Imports

#### ✅ CORRECT: Main Client

\`\`\`python
from azure.ai.mymodule import MyClient
from azure.identity import DefaultAzureCredential
\`\`\`

#### ❌ INCORRECT: Wrong Module Path

\`\`\`python
from azure.ai.mymodule.models import MyClient # Wrong - Client is not in models
\`\`\`

## 2. Authentication Patterns

#### ✅ CORRECT: DefaultAzureCredential + context manager

\`\`\`python
credential = DefaultAzureCredential()
with MyClient(endpoint, credential) as client:
client.do_thing()
\`\`\`

#### ❌ INCORRECT: Hardcoded Credentials

\`\`\`python
client = MyClient(endpoint, api_key="hardcoded") # Security risk
\`\`\`

#### ❌ INCORRECT: Connection string / account key when Entra is supported

\`\`\`python
client = MyClient.from_connection_string(os.environ["CONNECTION_STRING"]) # Bypasses Entra audit/rotation
\`\`\`

#### ❌ INCORRECT: Bare client without context manager

\`\`\`python
client = MyClient(endpoint, credential) # Leaks HTTP transport on exception / interpreter exit
client.do_thing()
\`\`\`

Critical patterns to document:

  • Import paths (these vary significantly between Azure SDKs)
  • Authentication patterns
  • Client initialization
  • Async variants (.aio modules)
  • Common anti-patterns

6.2 Create Test Scenarios

Location: tests/scenarios/<skill-name>/scenarios.yaml

config:
  model: gpt-4
  max_tokens: 2000
  temperature: 0.3

scenarios:
  - name: basic_client_creation
    prompt: |
      Create a basic example using the Azure SDK.
      Include proper authentication and client initialization.
    expected_patterns:
      - "DefaultAzureCredential"
      - "MyClient"
      - "with MyClient" # enforce context manager
    forbidden_patterns:
      - "api_key="
      - "hardcoded"
      - "from_connection_string" # prefer Entra over connection strings
    tags:
      - basic
      - authentication
    mock_response: |
      import os
      from azure.identity import DefaultAzureCredential
      from azure.ai.mymodule import MyClient

      credential = DefaultAzureCredential()
      with MyClient(
          endpoint=os.environ["AZURE_ENDPOINT"],
          credential=credential,
      ) as client:
          # ... rest of working example
          pass

Scenario design principles:

  • Each scenario tests ONE specific pattern or feature
  • expected_patterns — patterns that MUST appear
  • forbidden_patterns — common mistakes that must NOT appear
  • mock_response — complete, working code that passes all checks
  • tags — for filtering (basic, async, streaming, tools)

6.3 Run Tests

cd tests
pnpm install

# Check skill is discovered
pnpm harness --list

# Run in mock mode (fast, deterministic)
pnpm harness <skill-name> --mock --verbose

# Run with Ralph Loop (iterative improvement)
pnpm harness <skill-name> --ralph --mock --max-iterations 5 --threshold 85

Success criteria:

  • All scenarios pass (100% pass rate)
  • No false positives (mock responses always pass)
  • Patterns catch real mistakes

Step 7: Update Documentation

After creating the skill:

  1. Update README.md — Add the skill to the appropriate language section in the Skill Catalog

    • Update total skill count (line ~73: > N skills in...)
    • Update Skill Explorer link count (line ~15: Browse all N skills)
    • Update language count table (lines ~77-83)
    • Update language section count (e.g., > N skills • suffix: -py)
    • Update category count (e.g., <summary><strong>Foundry & AI</strong> (N skills)</summary>)
    • Add skill row in alphabetical order within its category
    • Update test coverage summary (line ~622: **N skills with N test scenarios**)
    • Update test coverage table — update skill count, scenario count, and top skills for the language
  2. Regenerate GitHub Pages data — Run the extraction script and rebuild the docs site from one scoped directory change

    (cd docs-site && npx tsx scripts/extract-skills.ts && npm run build)
    

    This updates docs-site/src/data/skills.json which feeds the Astro-based docs site, then rebuilds the site into docs/, which is served by GitHub Pages.

  3. Verify AGENTS.md — Ensure the skill count is accurate


Step 8: Regenerate Existing Skills from Latest SDK Sources

Use this workflow when an existing skill has stale examples, outdated API signatures, or changed package guidance.

  1. Identify canonical source files first

For Azure SDK language skills, use official upstream source docs and examples as the source of truth:

  • Go: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/<service>/<module>/README.md
  • Go examples: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/<service>/<module>/
  • Rust: https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/<service>/<crate>/README.md
  • Rust examples: https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/<service>/<crate>/examples/
  • .NET/Java/Python/TS/Go: use current Microsoft Learn package docs + official SDK repos
  1. Refresh skill content surgically
  • Update code snippets to match current constructor/method signatures
  • Keep crate/package names aligned with official publisher guidance
  • Preserve skill structure/frontmatter unless intentionally changing behavior
  • Update "Best Practices" and "Reference Links" when upstream recommendations change
  • For Rust, if code uses azure_core types/imports directly, ensure azure_core is present in Cargo.toml; if only service-crate re-exports are used, direct azure_core dependency is optional

API Surface Parity Gate (required for every regenerated skill)

Use the language-specific authoritative source as the contract for every snippet in the regenerated skill:

  • Python, .NET, Java, TypeScript, Go: Treat the current Microsoft Learn API reference as the contract.
  • Rust: Treat the official SDK repository (https://github.com/Azure/azure-sdk-for-rust) and crates.io documentation as the contract; Rust packages do not have Learn API-reference pages.

Before finalizing any regenerated skill:

  1. Identify each SDK type/method shown in snippets (clients, operation groups, model constructors, enum members, long-running methods like begin_*).
  2. Verify each symbol and signature against the authoritative source for that language/package (see above).
  3. If the authoritative source shows a different shape (for example nested properties=... models, renamed methods, begin_* LRO methods), update the snippet to match.
  4. Re-check imports so model/client modules match the authoritative source exactly.
  5. Do not keep compatibility shortcuts that contradict authoritative examples in primary snippets.

Scenario Coverage Gate (required for every regenerated skill, all languages)

Regeneration is not complete when snippets compile — it is complete when the skill demonstrates real usage breadth.

Before finalizing any regenerated skill:

  1. Identify hero scenarios from the current authoritative docs/samples for that SDK (Microsoft Learn where available; otherwise the upstream SDK repo and package documentation).
  2. Ensure each hero scenario is represented in the skill with copy-pastable snippets (or an explicit link to a bundled reference file when too large).
  3. Add/refresh test scenarios so hero flows are validated by harness patterns.
  4. Add at least one important non-hero scenario (for example: update/patch, delete/cleanup, export/import, advanced auth mode, paging/filtering, retries/error handling, or LRO monitoring) when supported by the SDK. For Python SDKs that support both sync and async clients, present both forms with equal priority; do not treat either as universally preferred.
  5. For Azure SDK skills, structure references/ as:
    • references/capabilities.md as a concise index that records each hero scenario and where it is covered (SKILL.md or a bundled reference), plus links to deeper non-hero references, with no historical/migration narration.
    • references/non-hero-scenarios.md for concrete non-hero examples that are intentionally kept out of the main SKILL.md.
    • Additional references/*.md files for specialized deep-dives (operation groups, tools, evaluator matrices, etc.).
  6. If the SDK has broad operation-group coverage (common in management SDKs), include an operation-group table and explicitly call out which groups are covered in snippets vs. referenced only.
  7. Never claim "full API surface" unless the skill genuinely demonstrates all major operation groups; otherwise state that the skill is optimized for hero workflows plus selected secondary scenarios.

Regeneration Workflow Step 3: Validate Regenerated Skill Behavior

(cd tests && pnpm harness <skill-name> --mock --verbose)

If the skill has a Vally scenario, run that eval as well (locally or in CI) before finalizing.

Rust regeneration gate (required for Rust skills):

When regenerating any Rust skill, verify the generated ## Best Practices section contains these exact first two rules:

  1. Use cargo add to manage dependencies, never edit Cargo.toml directly
  2. Add azure_core only when importing azure_core types directly

Use a content check before finalizing:

rg -n "Use `cargo add` to manage dependencies, never edit `Cargo.toml` directly|Add `azure_core` only when importing `azure_core` types directly" .github/plugins/azure-sdk-rust/skills/**/SKILL.md

The regeneration is not complete unless both lines are present in each affected Rust skill.

Regeneration Workflow Step 4: Regenerate Docs Artifacts After Refresh

(cd docs-site && npx tsx scripts/extract-skills.ts && npm run build)

Regeneration Workflow Step 5: Record What Changed

In the PR/commit notes, include:

  • Which upstream docs/examples were used
  • Which snippets/signatures were corrected
  • Which tests/evals were run and their outcomes

Python plugin batch recipe: azure-sdk-python

Use this when the request is "regenerate all Python skills under azure-sdk-python."

  1. Scope the exact targets first
# Canonical source of truth for Python plugin skills
ls .github/plugins/azure-sdk-python/skills/*/SKILL.md
  • Treat .github/plugins/azure-sdk-python/skills/ as canonical.
  • Keep .github/skills/<name> links in sync after edits (symlink check/fix step below).
  1. For each skill, refresh from authoritative sources
  • Always use microsoft-docs MCP first for current Microsoft Learn API guidance.
  • Verify the installed package version with pip show <package>, then inspect the installed package or official API reference to verify every symbol and signature used in snippets.
  • For Azure SDK skills, prefer package overview + official SDK repo examples.
  • For non-Azure Python skills in this plugin (for example fastapi-router-py, pydantic-models-py), keep language-specific best-practice variants and skip Azure-specific auth callouts when lifecycle/auth is not applicable.
  1. Apply Python enforcement rules consistently
  • Keep the standard section order for Azure SDK Python skills.
  • Ensure ## Authentication & Lifecycle starts with the required callout block (verbatim) when applicable.
  • Ensure every client example uses with / async with lifecycle patterns.
  • Ensure `## Best
Files (skills)
  • references
    • azure-sdk-patterns.md 31.8 KB
      # Azure SDK Patterns by Language
      
      Reference for creating skills that teach agents to write code following official Azure SDK guidelines.
      
      **Official Documentation:** <https://azure.github.io/azure-sdk/>
      
      ---
      
      ## Table of Contents
      
      1. [Core Principles (All Languages)](#core-principles-all-languages)
      2. [Skill Reference Directory Pattern](#skill-reference-directory-pattern)
      3. [Standard Naming Conventions](#standard-naming-conventions)
      4. [Python Patterns](#python-patterns)
      5. [.NET (C#) Patterns](#net-c-patterns)
      6. [Java Patterns](#java-patterns)
      7. [TypeScript/JavaScript Patterns](#typescriptjavascript-patterns)
      8. [Rust Patterns](#rust-patterns)
      9. [Authentication (All Languages)](#authentication-all-languages)
      10. [Quick Reference Tables](#quick-reference-tables)
      
      ---
      
      ## Core Principles (All Languages)
      
      Azure SDKs follow five design principles. Skills should reinforce these:
      
      | Principle | Meaning |
      | --------- | ------- |
      | **Idiomatic** | Follow language conventions; feel natural to developers |
      | **Consistent** | APIs feel like a single product from a single team |
      | **Approachable** | Great docs, predictable defaults, progressive disclosure |
      | **Diagnosable** | Clear logging, errors are actionable and human-readable |
      | **Dependable** | No breaking changes without major version bump |
      
      **Consistency Priority:** Language conventions > Service conventions > Cross-language conventions
      
      ---
      
      ## Skill Reference Directory Pattern
      
      For Azure SDK skills, keep `SKILL.md` focused on hero flows and use `references/` for overflow details:
      
      - `references/capabilities.md` is an index only: each hero scenario plus where it is covered (`SKILL.md` or a bundled reference), the non-hero scenario list, and links to deep-dive reference files.
      - `references/non-hero-scenarios.md` contains concrete non-hero examples intentionally kept out of `SKILL.md`.
      - Additional `references/*.md` files are optional for specialized topics (operation groups, evaluator/tool matrices, migration notes).
      
      Use present-tense guidance in reference files; avoid historical migration notes in user-facing capability indexes.
      
      For Python SDK skills that provide both sync and async clients, present both forms as first-class options with equal priority. Do not encode a blanket preference for either mode in capability prioritization. When the SDK is sync-only or async-only, document the available mode only.
      
      ---
      
      ## Standard Naming Conventions
      
      ### Namespace/Package Format
      
      `<Azure>.<group>.<service>`
      
      | Group | Area | Examples |
      | ----- | ---- | -------- |
      | `ai` | AI/ML services | `Azure.AI.OpenAI`, `azure-ai-agents` |
      | `data` | Databases | `Azure.Data.Cosmos`, `azure-cosmos` |
      | `storage` | Storage services | `Azure.Storage.Blobs`, `@azure/storage-blob` |
      | `identity` | Auth/Identity | `Azure.Identity`, `azure-identity` |
      | `messaging` | Messaging | `Azure.Messaging.ServiceBus` |
      | `security` | Security/Crypto | `Azure.Security.KeyVault` |
      
      ### Standard Verb Prefixes (All Languages)
      
      | Verb | Behavior | Returns |
      | ---- | -------- | ------- |
      | `create` | Create new; fail if exists | Created item |
      | `upsert` | Create or update (database-like) | Item |
      | `set` | Create or update (dictionary-like) | Item |
      | `update` | Fail if doesn't exist | Updated item |
      | `get` | Retrieve single; error if missing | Item |
      | `list` | Return collection (empty if none) | Pageable |
      | `delete` | Succeed even if doesn't exist | void/None |
      | `exists` | Check existence | boolean |
      | `begin` | Start long-running operation | Poller |
      
      ---
      
      ## Python Patterns
      
      ### Python Client Naming
      
      ```python
      # Sync client
      class ConfigurationClient:
          pass
      
      # Async client - use Async prefix
      class AsyncConfigurationClient:
          pass
      ```
      
      ### Sync vs Async: Don't Mix Within a Call Path
      
      **Rule:** Within a single module, script, or code path, use **either** the sync client **or** the async client — never both.
      
      - Sync clients live in `azure.<service>` (e.g., `azure.ai.projects.AIProjectClient`).
      - Async clients live in `azure.<service>.aio` (e.g., `azure.ai.projects.aio.AIProjectClient`).
      - Mixing sync calls inside an `async def` (or awaiting inside a sync function) blocks the event loop, breaks context managers, and produces subtle concurrency bugs.
      
      ```python
      # Setup used by the snippets below
      endpoint = "https://example.services.ai.azure.com/api/projects/example"
      
      # ✅ Good — all sync
      from azure.ai.projects import AIProjectClient
      from azure.identity import DefaultAzureCredential
      
      with AIProjectClient(endpoint=endpoint, credential=DefaultAzureCredential()) as client:
          agent = client.agents.get_agent("agent-id")
      
      # ✅ Good — all async
      from azure.ai.projects.aio import AIProjectClient as AsyncAIProjectClient
      from azure.identity.aio import DefaultAzureCredential as AsyncDefaultAzureCredential
      
      async def run_async():
          async with AsyncDefaultAzureCredential() as credential, \
                     AsyncAIProjectClient(endpoint=endpoint, credential=credential) as client:
              agent = await client.agents.get_agent("agent-id")
      
      # ❌ Bad — sync client (azure.ai.projects) called from an async function:
      # the synchronous HTTP call blocks the event loop for the entire request.
      async def run_bad():
          from azure.ai.projects import AIProjectClient  # sync client lives in azure.<service>
          with AIProjectClient(endpoint=endpoint, credential=DefaultAzureCredential()) as client:
              client.agents.get_agent("agent-id")  # ← blocking call inside `async def`
      
      # ❌ Bad — async client (azure.<service>.aio) paired with sync DefaultAzureCredential:
      # the async client expects an async credential from azure.identity.aio.
      async def run_also_bad():
          from azure.identity import DefaultAzureCredential          # sync
          from azure.ai.projects.aio import AIProjectClient          # async
          async with AIProjectClient(endpoint=endpoint, credential=DefaultAzureCredential()) as client:
              await client.agents.get_agent("agent-id")  # credential.get_token() will block
      ```
      
      When writing a skill, present both sync and async forms as first-class options with equal priority when the SDK provides both. Do not encode a preference for either mode. When the SDK is sync-only or async-only, document the available mode only.
      
      ### Pagination: ItemPaged / AsyncItemPaged
      
      ```python
      from azure.core.paging import ItemPaged
      
      # Sync iteration
      for item in client.list_items():
          print(item.name)
      
      # Page-by-page
      for page in client.list_items().by_page():
          for item in page:
              print(item.name)
      
      # With continuation token
      for page in client.list_items().by_page(continuation_token="..."):
          print(page)
      
      # Async iteration
      async for item in async_client.list_items():
          print(item.name)
      ```
      
      ### Long-Running Operations: LROPoller / AsyncLROPoller
      
      ```python
      from azure.core.polling import LROPoller
      
      # Start LRO
      poller: LROPoller[Result] = client.begin_create_resource(config)
      
      # Check status
      if poller.done():
          result = poller.result()
      
      # Wait with timeout
      result = poller.result(timeout=60)
      
      # Async LRO
      async_poller = await async_client.begin_create_resource(config)
      result = await async_poller.result()
      ```
      
      ### Context Managers (Strongly Preferred)
      
      **Always prefer context managers (`with` / `async with`) over manually constructing and closing clients.** They guarantee the underlying HTTP transport and credential sessions are closed, even on exceptions, and make the sync/async choice explicit at the call site.
      
      ```python
      # ✅ Preferred — sync
      with ConfigurationClient(endpoint, credential) as client:
          setting = client.get_setting("key")
      
      # ✅ Preferred — async (also wrap the async credential)
      from azure.identity.aio import DefaultAzureCredential
      
      async with DefaultAzureCredential() as credential, \
                 AsyncConfigurationClient(endpoint, credential) as client:
          setting = await client.get_setting("key")
      
      # ⚠️ Only acceptable when the client lifetime spans the whole app
      # (e.g., FastAPI lifespan, long-running service). Close it explicitly.
      client = ConfigurationClient(endpoint, credential)
      try:
          setting = client.get_setting("key")
      finally:
          client.close()  # or `await client.close()` for async clients
      ```
      
      Skills should show the context-manager form first. Only introduce the explicit `close()` pattern when the scenario genuinely requires a long-lived client (e.g., dependency-injected singletons), and always pair it with `try/finally` or a framework lifecycle hook.
      
      ### Python Error Handling
      
      ```python
      from azure.core.exceptions import (
          ResourceNotFoundError,
          ResourceExistsError,
          HttpResponseError,
      )
      
      try:
          item = client.get_item("key")
      except ResourceNotFoundError:
          print("Not found")
      except HttpResponseError as e:
          print(f"HTTP {e.status_code}: {e.message}")
      ```
      
      ### Docstring Format (Sphinx-style)
      
      ```python
      def get_setting(self, key: str, **kwargs) -> "ConfigurationSetting":
          """Retrieve a configuration setting.
      
          :param key: The key of the setting.
          :type key: str
          :keyword timeout: Operation timeout in seconds.
          :paramtype timeout: int
          :returns: The configuration setting.
          :rtype: ~azure.appconfig.ConfigurationSetting
          :raises ~azure.core.exceptions.ResourceNotFoundError: If setting not found.
          """
      ```
      
      ---
      
      ## .NET (C#) Patterns
      
      ### .NET Client Naming
      
      ```csharp
      namespace Azure.Data.Configuration
      {
          // Service client with Client suffix
          public class ConfigurationClient { }
          
          // Options class
          public class ConfigurationClientOptions : ClientOptions { }
      }
      ```
      
      ### .NET Response Wrapper: `Response<T>`
      
      ```csharp
      // Single item
      public Response<ConfigurationSetting> GetSetting(string key);
      public Task<Response<ConfigurationSetting>> GetSettingAsync(string key);
      
      // No content
      public Response DeleteSetting(string key);
      public Task<Response> DeleteSettingAsync(string key);
      ```
      
      ### .NET Pagination: `Pageable<T>` / `AsyncPageable<T>`
      
      ```csharp
      // Sync
      foreach (ConfigurationSetting setting in client.GetSettings())
      {
          Console.WriteLine(setting.Key);
      }
      
      // Async
      await foreach (ConfigurationSetting setting in client.GetSettingsAsync())
      {
          Console.WriteLine(setting.Key);
      }
      ```
      
      ### .NET Long-Running Operations: `Operation<T>`
      
      ```csharp
      // With WaitUntil parameter
      Operation<AnalyzeResult> operation = await client.StartAnalyzeAsync(
          WaitUntil.Completed,  // or WaitUntil.Started
          document);
      
      AnalyzeResult result = operation.Value;
      
      // Manual polling
      Operation<AnalyzeResult> operation = await client.StartAnalyzeAsync(
          WaitUntil.Started, document);
      
      while (!operation.HasCompleted)
      {
          await operation.UpdateStatusAsync();
          await Task.Delay(1000);
      }
      ```
      
      ### Mocking Support
      
      ```csharp
      public class ConfigurationClient
      {
          // Protected parameterless constructor for mocking
          protected ConfigurationClient() { }
          
          // Virtual methods for mocking
          public virtual Response<ConfigurationSetting> GetSetting(string key);
      }
      ```
      
      ### .NET Error Handling
      
      ```csharp
      try
      {
          var setting = await client.GetSettingAsync("key");
      }
      catch (RequestFailedException ex) when (ex.Status == 404)
      {
          Console.WriteLine("Not found");
      }
      catch (RequestFailedException ex)
      {
          Console.WriteLine($"Error: {ex.Status} - {ex.ErrorCode}");
      }
      ```
      
      ---
      
      ## Java Patterns
      
      ### Java Client Naming
      
      ```java
      // Sync client
      public final class ConfigurationClient { }
      
      // Async client
      public final class ConfigurationAsyncClient { }
      
      // Builder (the ONLY way to create clients)
      public final class ConfigurationClientBuilder {
          public ConfigurationClient buildClient() { }
          public ConfigurationAsyncClient buildAsyncClient() { }
      }
      ```
      
      ### Builder Pattern
      
      ```java
      ConfigurationClient client = new ConfigurationClientBuilder()
          .endpoint(endpoint)
          .credential(new DefaultAzureCredentialBuilder().build())
          .serviceVersion(ConfigurationServiceVersion.V2023_10_01)
          .buildClient();
      ```
      
      ### Java Pagination: `PagedIterable<T>` / `PagedFlux<T>`
      
      ```java
      // Sync - standard for loop
      for (ConfigurationSetting setting : client.listSettings()) {
          System.out.println(setting.getKey());
      }
      
      // Sync - Stream API
      client.listSettings().stream()
          .filter(s -> s.getKey().startsWith("app"))
          .forEach(System.out::println);
      
      // Async - Reactor
      client.listSettings()
          .subscribe(setting -> System.out.println(setting.getKey()));
      ```
      
      ### Long-Running Operations: SyncPoller<T,U> / PollerFlux<T,U>
      
      ```java
      // Sync
      SyncPoller<OperationResult, AnalyzeResult> poller = 
          client.beginAnalyze(document);
      poller.waitForCompletion();
      AnalyzeResult result = poller.getFinalResult();
      
      // Async
      client.beginAnalyze(document)
          .last()
          .flatMap(AsyncPollResponse::getFinalResult)
          .subscribe(result -> System.out.println(result));
      ```
      
      ### Reactor Types
      
      | Type | Purpose |
      | ---- | ------- |
      | `Mono<T>` | 0 or 1 item |
      | `Flux<T>` | 0 to N items |
      | `PagedFlux<T>` | Paginated collections |
      | `PollerFlux<T,U>` | Long-running operations |
      
      ### Annotations
      
      ```java
      @ServiceClient(builder = ConfigurationClientBuilder.class)
      public final class ConfigurationClient {
          
          @ServiceMethod(returns = ReturnType.SINGLE)
          public ConfigurationSetting getSetting(String key) { }
          
          @ServiceMethod(returns = ReturnType.COLLECTION)
          public PagedIterable<ConfigurationSetting> listSettings() { }
      }
      ```
      
      ---
      
      ## TypeScript/JavaScript Patterns
      
      ### Package Naming
      
      ```typescript
      // Package: @azure/service-name (kebab-case)
      // Client: ServiceClient (PascalCase with Client suffix)
      
      import { ServiceClient } from "@azure/service-name";
      ```
      
      ### Pagination: PagedAsyncIterableIterator
      
      ```typescript
      // Iterate items
      for await (const item of client.listItems()) {
          console.log(item.name);
      }
      
      // Iterate by page
      for await (const page of client.listItems().byPage()) {
          console.log(`Page has ${page.length} items`);
      }
      
      // With continuation token
      const iterator = client.listItems().byPage({ continuationToken });
      ```
      
      ### Long-Running Operations
      
      ```typescript
      // Methods starting LRO use 'begin' prefix
      const poller = await client.beginAnalyzeDocument(modelId, document, {
          pollInterval: 2000
      });
      
      // Wait for completion
      const result = await poller.pollUntilDone();
      
      // Serialize state for later
      const state = poller.toString();
      const restored = await client.beginAnalyzeDocument(modelId, document, {
          resumeFrom: state
      });
      ```
      
      ### Cancellation: AbortSignal
      
      ```typescript
      import { AbortController } from "@azure/abort-controller";
      
      const controller = new AbortController();
      setTimeout(() => controller.abort(), 5000);
      
      try {
          const item = await client.createItem({
              abortSignal: controller.signal
          });
      } catch (e) {
          if (e.name === "AbortError") {
              console.log("Cancelled");
          }
      }
      ```
      
      ### Options Pattern
      
      ```typescript
      interface CreateItemOptions {
          abortSignal?: AbortSignalLike;
          timeoutInMs?: number;        // Duration suffix: InMs, InSeconds
          onlyIfChanged?: boolean;     // Conditional request
      }
      ```
      
      ### TypeScript Error Handling
      
      ```typescript
      import { RestError } from "@azure/core-rest-pipeline";
      
      try {
          await client.createItem(item);
      } catch (e) {
          // Check name, not instanceof
          if (e.name === "RestError") {
              console.error(`HTTP ${e.statusCode}: ${e.message}`);
          }
      }
      ```
      
      ---
      
      ## Rust Patterns
      
      > **IMPORTANT:** Only use the official `azure_*` crates published by the [azure-sdk](https://crates.io/users/azure-sdk) crates.io user (e.g., `azure_core`, `azure_identity`, `azure_security_keyvault_secrets`). Do **NOT** use the deprecated unofficial crates (`azure_sdk_*` from MindFlavor/AzureSDKForRust) or the community crates (e.g., `azure_storage`, or `azure_storage_blobs` from the `azure_sdk_for_rust` ecosystem). The official crates use underscores in their names and are installed via `cargo add`. None of the official crates have a version number of 0.21.0. **Only create or modify crates using `cargo` commands; avoid modifying `Cargo.toml` files directly if at all possible.**
      >
      > **Source:** All examples below are derived from the official [azure-sdk-for-rust](https://github.com/Azure/azure-sdk-for-rust) repository README files and examples.
      >
      > **Dependency rule:** If your Rust code imports `azure_core` types directly (for example, `azure_core::http::Url`, `azure_core::http::RequestContent`, or `azure_core::error::ErrorKind`), add `azure_core` to `Cargo.toml`. If you only use types re-exported by service crates, a direct `azure_core` dependency is optional.
      >
      
      ### Installation (Rust)
      
      For Rust SDK skills, include the Installation section as:
      
      ```markdown
      ## Installation
      
      \`\`\`sh
      cargo add <crate1> <crate2> <crate3> ...
      \`\`\`
      
      > If your code uses \`azure_core\` types directly (for example, \`azure_core::http::Url\` or \`azure_core::http::RequestContent\`), add \`azure_core\` to \`Cargo.toml\`. If you only use types re-exported by service crates, direct \`azure_core\` dependency is optional.
      ```
      
      **Key points:**
      
      - Always use `cargo add`, never show `Cargo.toml` manual edits
      - List all direct dependencies needed for the examples in the skill
      - Include the optional note about `azure_core` (copy verbatim) so users understand when to add it explicitly
      - If examples use `RequestContent::from()`, include `azure_core` in the install list since that's a direct `azure_core` type usage
      
      ### Regenerating Rust SDK Skills from Latest Sources
      
      When a Rust skill appears stale (wrong signatures, outdated examples, deprecated guidance),
      regenerate it from current upstream sources before editing anything else.
      
      1. Collect authoritative sources:
          - crate README: `sdk/<service>/<crate>/README.md`
          - executable examples: `sdk/<service>/<crate>/examples/*.rs`
          - if needed, public API surface in `src/clients` / `src/generated`
      
      2. Rebuild skill snippets from those sources:
          - prefer README + examples over ad-hoc internet snippets
          - align constructor signatures, async patterns, pager/poller usage, and error handling
          - keep crate guidance strict: official `azure_*` crates published by `azure-sdk`
      
      3. Re-validate quality gates:
          - run harness scenarios for the affected skill
          - run Vally eval if the skill has one (for example, `tests/scenarios/azure-storage-blob-rust/vally/eval.yaml`)
      
      4. Update reference links in the skill to the exact crate docs and source directory used.
      
      ### Crate Naming
      
      ```rust
      // Crate: azure_<group>_<service> (underscores, all lowercase)
      // Client: ServiceClient (PascalCase with Client suffix)
      
      use azure_security_keyvault_secrets::SecretClient;
      use azure_security_keyvault_keys::KeyClient;
      use azure_security_keyvault_certificates::CertificateClient;
      use azure_storage_blob::BlobClient;
      use azure_data_cosmos::CosmosClient;
      use azure_messaging_eventhubs::ProducerClient;
      ```
      
      ### Client Construction
      
      Client construction varies by service. Some use `Client::new()`, others use builders.
      
      #### Key Vault: `Client::new()` function
      
      ```rust
      use azure_identity::DeveloperToolsCredential;
      use azure_security_keyvault_secrets::SecretClient;
      
      let credential = DeveloperToolsCredential::new(None)?;
      let client = SecretClient::new(
          "https://<your-key-vault-name>.vault.azure.net/",
          credential.clone(),
          None, // Optional SecretClientOptions
      )?;
      
      // Get a secret
      let secret = client.get_secret("secret-name", None).await?.into_model()?;
      println!("Secret: {:?}", secret.value);
      ```
      
      ```rust
      use azure_core::http::Url;
      use azure_identity::DeveloperToolsCredential;
      use azure_storage_blob::BlobServiceClient;
      
      let credential = DeveloperToolsCredential::new(None)?;
      let service_client = BlobServiceClient::new(service_url, Some(credential), None)?;
      let blob_client = service_client.blob_client("<container_name>", "<blob_name>");
      ```
      
      ```rust
      use azure_identity::DeveloperToolsCredential;
      use azure_data_cosmos::{CosmosClient, AccountReference, AccountEndpoint};
      
      let credential = DeveloperToolsCredential::new(None)?;
      let endpoint: AccountEndpoint = "https://myaccount.documents.azure.com/".parse()?;
      let account = AccountReference::with_credential(endpoint, credential);
      let cosmos_client = CosmosClient::builder().build(account).await?;
      ```
      
      #### Event Hubs: Builder with `open()`
      
      ```rust
      use azure_identity::DeveloperToolsCredential;
      use azure_messaging_eventhubs::ProducerClient;
      
      let credential = DeveloperToolsCredential::new(None)?;
      let producer = ProducerClient::builder()
          .open("<EVENTHUBS_HOST>", "<EVENTHUB_NAME>", credential.clone())
          .await?;
      ```
      
      ### Response Wrapper: `Response<T>`
      
      ```rust
      // Call a service method returning Response<T>
      let response = client.get_secret("secret-name", None).await?;
      
      // Deserialize into a model
      let secret = response.into_model()?;
      
      // Or deconstruct for HTTP details
      let (status, headers, body) = response.deconstruct();
      ```
      
      ### Pagination: `Pager<T>`
      
      ```rust
      use futures::TryStreamExt;
      
      // Iterate all items across all pages
      let mut pager = client.list_secret_properties(None)?;
      while let Some(secret) = pager.try_next().await? {
          let name = secret.resource_id()?.name;
          println!("Found Secret: {}", name);
      }
      
      ```
      
      Skills should explicitly document the concrete item yielded by `try_next()` for the specific SDK being taught. Do not infer the public iteration shape from generated internal model names alone.
      
      - Some Rust Azure clients expose flattened item iteration, where `try_next()` already yields the item to process.
      - Others expose response pages or wrapper models that require an additional loop.
      - If the service skill is storage-specific, show the exact public `list_*` example from the crate README or examples instead of a generic pager explanation.
      
      The `ResourceExt` trait provides `resource_id()` for parsing names and versions from resource IDs:
      
      ```rust
      use azure_security_keyvault_secrets::ResourceExt;
      
      let secret = client.get_secret("my-secret", None).await?.into_model()?;
      let id = secret.resource_id()?;
      println!("Name: {}, Version: {:?}", id.name, id.version);
      ```
      
      ### Long-Running Operations: `Poller<T>`
      
      LRO methods use the `begin_` prefix. The `Poller` implements `IntoFuture` — just await it:
      
      ```rust
      use azure_security_keyvault_certificates::models::{
          CertificatePolicy, CreateCertificateParameters, IssuerParameters, X509CertificateProperties,
      };
      
      let policy = CertificatePolicy {
          x509_certificate_properties: Some(X509CertificateProperties {
              subject: Some("CN=DefaultPolicy".into()),
              ..Default::default()
          }),
          issuer_parameters: Some(IssuerParameters {
              name: Some("Self".into()),
              ..Default::default()
          }),
          ..Default::default()
      };
      let body = CreateCertificateParameters {
          certificate_policy: Some(policy),
          ..Default::default()
      };
      
      // Wait for completion — Poller implements IntoFuture and automatically waits between polls
      let certificate = client
          .begin_create_certificate("cert-name", body.try_into()?, None)?
          .await?
          .into_model()?;
      ```
      
      ### Rust Error Handling
      
      Key Vault services return structured errors via `err.into_inner()?`:
      
      ```rust
      match client.get_secret("secret-name", None).await {
          Ok(response) => println!("Secret Value: {:?}", response.into_model()?.value),
          Err(err) => println!("Error: {:#?}", err.into_inner()?),
      }
      // Error output includes structured ErrorResponse with code and message:
      // ErrorResponse {
      //     error: ErrorDetails {
      //         code: Some("SecretNotFound"),
      //         message: Some("A secret with (name/id) secret-name was not found..."),
      //     },
      //     ..
      // }
      ```
      
      Storage client error handling uses `StorageError`:
      
      ```rust
      use azure_core::error::ErrorKind;
      use azure_storage_blob::StorageError;
      use azure_storage_blob::models::StorageErrorCode;
      
      match blob_client.download(None).await {
          Ok(response) => { /* process response */ }
          Err(error) => {
              if matches!(error.kind(), ErrorKind::HttpResponse { .. }) {
                  let storage_error: StorageError = error.try_into()?;
                  println!("Status: {}", storage_error.status_code);
                  if let Some(error_code) = &storage_error.error_code {
                      match error_code {
                          StorageErrorCode::BlobNotFound => println!("Blob does not exist."),
                          StorageErrorCode::ContainerNotFound => println!("Container does not exist."),
                          StorageErrorCode::AuthorizationFailure => println!("Auth failed."),
                          _ => println!("Other error: {error_code}"),
                      }
                  }
              }
          }
      }
      ```
      
      Note that `StorageError::try_into` requires an owned error object, it will not compile if handed a reference to an error.
      
      ### Model Types
      
      ```rust
      // Request/response models: Clone + Default + Serialize/Deserialize
      // All non-vector fields are Option<T>
      // Response-only models are #[non_exhaustive]
      // Use ..Default::default() for struct update syntax
      let parameters = UpdateSecretPropertiesParameters {
          content_type: Some("text/plain".into()),
          tags: Some(HashMap::from_iter(vec![("key".into(), "value".into())])),
          ..Default::default()
      };
      
      // Cosmos DB uses serde for document types
      use serde::{Serialize, Deserialize};
      
      #[derive(Serialize, Deserialize)]
      struct Item {
          pub id: String,
          pub partition_key: String,
          pub value: String,
      }
      ```
      
      When documenting Rust model types, explicitly teach users how to handle `#[non_exhaustive]` structs and enums:
      
      - When constructing SDK model structs, always include `..Default::default()` even if every currently known field is set.
      - When matching SDK enums, include a wildcard arm so future service-added variants do not break the match.
      - If Clippy or the compiler flags those future-proofing patterns in a minimal example, it is acceptable to locally suppress the warning on that example.
      
      ```rust
      #![allow(dead_code, unused_variables)]
      
      #[derive(Default)]
      struct Model {
          one: Option<String>,
          two: Option<i32>,
      }
      
      enum E {
          One,
          Two,
      }
      
      fn main() {
          // Future-proof struct construction for non-exhaustive SDK models.
          #[allow(clippy::needless_update)]
          let model = Model {
              one: Some("one".into()),
              two: Some(2),
              ..Default::default()
          };
      
          // Future-proof enum matching for non-exhaustive SDK enums.
          let value = E::One;
          match value {
              E::One => println!("One"),
              E::Two => println!("Two"),
              #[allow(unreachable_patterns)]
              _ => panic!("unexpected variant"),
          };
      }
      ```
      
      ### Async Only
      
      The Rust SDK provides **only async** methods. No sync wrappers:
      
      ```rust
      #[tokio::main]
      async fn main() -> Result<(), Box<dyn std::error::Error>> {
          let credential = DeveloperToolsCredential::new(None)?;
          let client = SecretClient::new(endpoint, credential.clone(), None)?;
          let secret = client.get_secret("name", None).await?.into_model()?;
          Ok(())
      }
      ```
      
      ### Key Differences from Other Azure SDKs
      
      | Aspect | Rust | Other Languages |
      | ------ | ---- | --------------- |
      | Auth default | `DeveloperToolsCredential` | `DefaultAzureCredential` |
      | Client creation | `Client::new()` or builder pattern (varies by service) | Constructors or builders |
      | Sync support | Async only (tokio) | Sync + Async |
      | Options | `Option<ClientOptions>` param | Separate options class |
      | Response access | `response.into_model()?` | Direct return or `.Value` |
      | LRO prefix | `begin_` prefix (e.g., `begin_create_certificate`) | `begin_` or `Begin` |
      | Debug safety | `SafeDebug` derive (redacts PII) | Standard debug |
      | Pagination stream | `futures::TryStreamExt` | Language iterators |
      | Serialization | `serde` for Cosmos DB documents | Built-in serializers |
      | Thread safety | All clients are `Send + Sync`; reuse is safe | Same guarantee |
      
      ### Rust Skill Authoring Guardrails
      
      When writing or refreshing a Rust Azure SDK skill, include explicit anti-pattern callouts for the mistakes most likely to happen when an agent generalizes from other languages:
      
      - Name the exact credential type to use, and name at least one tempting but invalid credential type if cross-language confusion is likely.
      - Show the exact pager item shape for the relevant service client and say whether `try_next()` yields items or pages.
      - Call out optional SDK fields that cannot be printed directly with `{}` and show the idiomatic fallback pattern.
      - If the target scenario or eval expects strict linting, say so explicitly and require `cargo clippy -- -D warnings` as a completion gate.
      - Prefer examples copied from the service crate README or examples directory over reconstructed snippets from generated source.
      
      ---
      
      ## Authentication (All Languages)
      
      **Use the language-idiomatic primary credential pattern:**
      
      ### Python
      
      ```python
      from azure.identity import DefaultAzureCredential
      credential = DefaultAzureCredential()
      client = ServiceClient(endpoint, credential)
      ```
      
      ### .NET
      
      ```csharp
      var credential = new DefaultAzureCredential();
      var client = new ServiceClient(new Uri(endpoint), credential);
      ```
      
      ### Java
      
      ```java
      TokenCredential credential = new DefaultAzureCredentialBuilder().build();
      ServiceClient client = new ServiceClientBuilder()
          .endpoint(endpoint)
          .credential(credential)
          .buildClient();
      ```
      
      ### TypeScript
      
      ```typescript
      import { DefaultAzureCredential } from "@azure/identity";
      const credential = new DefaultAzureCredential();
      const client = new ServiceClient(endpoint, credential);
      ```
      
      ### Rust
      
      ```rust
      use azure_identity::DeveloperToolsCredential;
      
      // Key Vault, Storage: Client::new()
      let credential = DeveloperToolsCredential::new(None)?;
      let client = SecretClient::new(endpoint, credential.clone(), None)?;
      
      // Cosmos DB: Builder pattern
      let account = AccountReference::with_credential(endpoint.parse()?, credential);
      let cosmos_client = CosmosClient::builder().build(account).await?;
      
      // Event Hubs: Builder with open()
      let producer = ProducerClient::builder()
          .open(host, eventhub, credential.clone())
          .await?;
      ```
      
      > **Important:** Rust does not have `DefaultAzureCredential`. Skills for Rust should explicitly say “do not use `DefaultAzureCredential`” when there is any chance of cross-language confusion. Use `DeveloperToolsCredential` for development (tries Azure CLI, then Azure Developer CLI). Use `ManagedIdentityCredential` for production on Azure-hosted apps. See [Credential structures](https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/identity/azure_identity#credential-structures) for the full list.
      
      **Rules:**
      
      - Never hardcode credentials
      - Never persist/cache tokens manually (credential handles refresh)
      - Use environment variables for configuration
      
      ---
      
      ## Quick Reference Tables
      
      ### Client Types by Language
      
      | Pattern | Python | .NET | Java | TypeScript | Rust |
      | ------- | ------ | ---- | ---- | ---------- | ---- |
      | Sync Client | `Client` | `Client` | `Client` | `Client` | N/A (Async only) |
      | Async Client | `AsyncClient` | N/A (Async methods) | `AsyncClient` | N/A (Promise) | `Client` |
      | Builder | N/A | N/A | `ClientBuilder` | N/A | `new()` or builder (varies by service) |
      
      ### Pagination Types
      
      | Language | Sync | Async |
      | -------- | ---- | ----- |
      | Python | `ItemPaged[T]` | `AsyncItemPaged[T]` |
      | .NET | `Pageable<T>` | `AsyncPageable<T>` |
      | Java | `PagedIterable<T>` | `PagedFlux<T>` |
      | TypeScript | N/A | `PagedAsyncIterableIterator<T>` |
      | Rust | N/A | `Pager<T>` (via `futures::TryStreamExt`) |
      
      ### LRO Types
      
      | Language | Sync | Async |
      | -------- | ---- | ----- |
      | Python | `LROPoller[T]` | `AsyncLROPoller[T]` |
      | .NET | `Operation<T>` | `Operation<T>` |
      | Java | `SyncPoller<T,U>` | `PollerFlux<T,U>` |
      | TypeScript | N/A | `PollerLike<T>` |
      | Rust | N/A | `Poller<T>` (implements `IntoFuture` + `Stream`) |
      
      ### Response Wrappers
      
      | Language | Single Item | Collection |
      | -------- | ----------- | ---------- |
      | Python | Direct return | `ItemPaged[T]` |
      | .NET | `Response<T>` | `Pageable<T>` |
      | Java | Direct return | `PagedIterable<T>` |
      | TypeScript | `Promise<T>` | `PagedAsyncIterableIterator<T>` |
      | Rust | `Response<T>` | `Pager<T>` |
      
      ---
      
      ## Official Documentation Links
      
      - **General Guidelines:** <https://azure.github.io/azure-sdk/general_introduction.html>
      - **Python:** <https://azure.github.io/azure-sdk/python_design.html>
      - **.NET:** <https://azure.github.io/azure-sdk/dotnet_introduction.html>
      - **Java:** <https://azure.github.io/azure-sdk/java_introduction.html>
      - **TypeScript:** <https://azure.github.io/azure-sdk/typescript_introduction.html>
      - **Rust:** <https://azure.github.io/azure-sdk/rust_introduction.html>
      
      When creating Azure SDK skills, reference these docs via the `microsoft-docs` MCP for current API signatures.
      
    • output-patterns.md 4.1 KB
      # Output Patterns
      
      Patterns for producing consistent, high-quality output in skills.
      
      ## Template Pattern
      
      Provide templates for output format. Match strictness to requirements.
      
      **For strict requirements (API responses, data formats):**
      
      ```markdown
      ## Report structure
      
      ALWAYS use this exact template structure:
      
      # [Analysis Title]
      
      ## Executive summary
      [One-paragraph overview of key findings]
      
      ## Key findings
      - Finding 1 with supporting data
      - Finding 2 with supporting data
      - Finding 3 with supporting data
      
      ## Recommendations
      1. Specific actionable recommendation
      2. Specific actionable recommendation
      ```
      
      **For flexible guidance:**
      
      ```markdown
      ## Report structure
      
      Sensible default format; adapt as needed:
      
      # [Analysis Title]
      
      ## Executive summary
      [Overview]
      
      ## Key findings
      [Adapt sections based on what you discover]
      
      ## Recommendations
      [Tailor to the specific context]
      ```
      
      ## Examples Pattern
      
      For output quality dependent on examples, provide input/output pairs:
      
      ```markdown
      ## Commit message format
      
      Generate commit messages following these examples:
      
      **Example 1:**
      Input: Added user authentication with JWT tokens
      Output:
      feat(auth): implement JWT-based authentication
      
      Add login endpoint and token validation middleware
      
      **Example 2:**
      Input: Fixed bug where dates displayed incorrectly in reports
      Output:
      fix(reports): correct date formatting in timezone conversion
      
      Use UTC timestamps consistently across report generation
      
      Follow this style: type(scope): brief description, then detailed explanation.
      ```
      
      Examples help agents understand desired style more clearly than descriptions alone.
      
      ## Azure SDK Code Patterns
      
      ### Client Initialization Template
      
      ```python
      # Standard Azure SDK client setup
      import os
      from azure.identity import DefaultAzureCredential
      from azure.<service> import <Service>Client
      
      credential = DefaultAzureCredential()
      client = <Service>Client(
          endpoint=os.environ["AZURE_<SERVICE>_ENDPOINT"],
          credential=credential
      )
      ```
      
      ### CRUD Method Template
      
      ```python
      # Create
      item = client.create_<noun>(
          name="example",
          config=<Noun>Config(
              property1="value1",
              property2="value2"
          )
      )
      
      # Read
      item = client.get_<noun>(item_id)
      
      # List (with pagination)
      for item in client.list_<nouns>():
          print(item.name)
      
      # Update
      updated = client.update_<noun>(item_id, new_config)
      
      # Delete
      client.delete_<noun>(item_id)
      ```
      
      ### Async Client Template
      
      ```python
      import asyncio
      from azure.identity.aio import DefaultAzureCredential
      from azure.<service>.aio import <Service>Client
      
      async def main():
          credential = DefaultAzureCredential()
          async with <Service>Client(endpoint, credential) as client:
              # Async operations
              item = await client.get_<noun>(item_id)
              
              # Async pagination
              async for item in client.list_<nouns>():
                  print(item.name)
      
      asyncio.run(main())
      ```
      
      ### Error Handling Template
      
      ```python
      from azure.core.exceptions import (
          ResourceNotFoundError,
          ResourceExistsError,
          HttpResponseError,
      )
      
      try:
          result = client.get_<noun>(item_id)
      except ResourceNotFoundError:
          # Handle 404
          print(f"Resource {item_id} not found")
      except ResourceExistsError:
          # Handle 409
          print(f"Resource already exists")
      except HttpResponseError as e:
          # Handle other HTTP errors
          print(f"HTTP {e.status_code}: {e.message}")
      ```
      
      ### Feature Comparison Table Template
      
      ```markdown
      ## Clients
      
      | Client | Purpose | When to Use |
      |--------|---------|-------------|
      | `ServiceClient` | Core operations | Standard use cases |
      | `AsyncServiceClient` | Async operations | High-throughput scenarios |
      | `ServiceAdminClient` | Management | Creating/deleting resources |
      ```
      
      ### Environment Variables Template
      
      ```markdown
      ## Environment Variables
      
      | Variable | Required | Description |
      |----------|----------|-------------|
      | `AZURE_<SERVICE>_ENDPOINT` | Yes | Service endpoint URL |
      | `AZURE_<SERVICE>_KEY` | No | API key (alternative to DefaultAzureCredential) |
      | `AZURE_CLIENT_ID` | No | For service principal auth |
      | `AZURE_TENANT_ID` | No | For service principal auth |
      | `AZURE_CLIENT_SECRET` | No | For service principal auth |
      ```
      
    • workflows.md 3.1 KB
      # Workflow Patterns
      
      Patterns for structuring multi-step processes in skills.
      
      ## Sequential Workflows
      
      For complex tasks, break operations into clear steps. Provide an overview at the start:
      
      ```markdown
      Filling a PDF form involves these steps:
      
      1. Analyze the form (run analyze_form.py)
      2. Create field mapping (edit fields.json)
      3. Validate mapping (run validate_fields.py)
      4. Fill the form (run fill_form.py)
      5. Verify output (run verify_output.py)
      ```
      
      ## Conditional Workflows
      
      For tasks with branching logic, guide through decision points:
      
      ```markdown
      1. Determine the modification type:
         **Creating new content?** → Follow "Creation workflow" below
         **Editing existing content?** → Follow "Editing workflow" below
      
      2. Creation workflow: [steps]
      3. Editing workflow: [steps]
      ```
      
      ## Azure SDK Workflows
      
      ### CRUD Lifecycle Pattern
      
      ```markdown
      ## Working with [Resource]
      
      ### Create
      \`\`\`python
      resource = client.create_resource(name="example", config={...})
      \`\`\`
      
      ### Read
      \`\`\`python
      # Single item
      resource = client.get_resource("resource-id")
      
      # List with pagination
      for resource in client.list_resources():
          print(resource.name)
      \`\`\`
      
      ### Update
      \`\`\`python
      resource = client.update_resource("resource-id", new_config={...})
      \`\`\`
      
      ### Delete
      \`\`\`python
      client.delete_resource("resource-id")
      \`\`\`
      ```
      
      ### Long-Running Operation Pattern
      
      ```markdown
      ## Processing [Resource]
      
      Long-running operations use the poller pattern:
      
      \`\`\`python
      # Start operation
      poller = client.begin_process_resource(resource_id, config)
      
      # Option 1: Wait for completion
      result = poller.result()
      
      # Option 2: Poll with status updates
      while not poller.done():
          print(f"Status: {poller.status()}")
          time.sleep(5)
      result = poller.result()
      
      # Option 3: Use callback
      poller.add_done_callback(lambda r: print(f"Done: {r}"))
      \`\`\`
      ```
      
      ### Agent Lifecycle Pattern (Azure AI Agents)
      
      ```markdown
      ## Agent Workflow
      
      1. **Create Agent** with tools and instructions
      2. **Create Thread** for conversation
      3. **Add Messages** to thread
      4. **Run Agent** on thread
      5. **Process Response** (handle tool calls if needed)
      6. **Cleanup** - delete agent when done
      
      \`\`\`python
      # 1. Create
      agent = client.create_agent(model="gpt-4o", instructions="...")
      
      # 2-4. Thread, Message, Run
      thread = client.threads.create()
      client.messages.create(thread_id=thread.id, content="...")
      run = client.runs.create(thread_id=thread.id, agent_id=agent.id)
      
      # 5. Wait for completion
      while run.status in ["queued", "in_progress"]:
          run = client.runs.retrieve(thread_id=thread.id, run_id=run.id)
          time.sleep(1)
      
      # 6. Cleanup
      client.delete_agent(agent.id)
      \`\`\`
      ```
      
      ### Error Recovery Pattern
      
      ```markdown
      ## Error Handling
      
      \`\`\`python
      from azure.core.exceptions import (
          ResourceNotFoundError,
          ResourceExistsError,
          HttpResponseError,
      )
      
      try:
          result = client.get_resource("id")
      except ResourceNotFoundError:
          # Handle missing resource
          result = client.create_resource("id", default_config)
      except HttpResponseError as e:
          if e.status_code == 429:  # Rate limited
              time.sleep(e.retry_after or 60)
              result = client.get_resource("id")
          else:
              raise
      \`\`\`
      ```
      
  • scripts
    • init_skill.py 10.6 KB
      #!/usr/bin/env python3
      """
      Skill Initializer - Creates a new skill from template
      
      Usage:
          init_skill.py <skill-name> --path <path>
      
      Examples:
          init_skill.py my-new-skill --path skills/public
          init_skill.py my-api-helper --path skills/private
          init_skill.py custom-skill --path /custom/location
      """
      
      import sys
      from pathlib import Path
      
      
      SKILL_TEMPLATE = """---
      name: {skill_name}
      description: [TODO: Complete and informative explanation of what the skill does and when to use it. Include WHEN to use this skill - specific scenarios, file types, or tasks that trigger it.]
      ---
      
      # {skill_title}
      
      ## Overview
      
      [TODO: 1-2 sentences explaining what this skill enables]
      
      ## Structuring This Skill
      
      [TODO: Choose the structure that best fits this skill's purpose. Common patterns:
      
      **1. Workflow-Based** (best for sequential processes)
      - Works well when there are clear step-by-step procedures
      - Example: DOCX skill with "Workflow Decision Tree" → "Reading" → "Creating" → "Editing"
      - Structure: ## Overview → ## Workflow Decision Tree → ## Step 1 → ## Step 2...
      
      **2. Task-Based** (best for tool collections)
      - Works well when the skill offers different operations/capabilities
      - Example: PDF skill with "Quick Start" → "Merge PDFs" → "Split PDFs" → "Extract Text"
      - Structure: ## Overview → ## Quick Start → ## Task Category 1 → ## Task Category 2...
      
      **3. Reference/Guidelines** (best for standards or specifications)
      - Works well for brand guidelines, coding standards, or requirements
      - Example: Brand styling with "Brand Guidelines" → "Colors" → "Typography" → "Features"
      - Structure: ## Overview → ## Guidelines → ## Specifications → ## Usage...
      
      **4. Capabilities-Based** (best for integrated systems)
      - Works well when the skill provides multiple interrelated features
      - Example: Product Management with "Core Capabilities" → numbered capability list
      - Structure: ## Overview → ## Core Capabilities → ### 1. Feature → ### 2. Feature...
      
      Patterns can be mixed and matched as needed. Most skills combine patterns (e.g., start with task-based, add workflow for complex operations).
      
      Delete this entire "Structuring This Skill" section when done - it's just guidance.]
      
      ## [TODO: Replace with the first main section based on chosen structure]
      
      [TODO: Add content here. See examples in existing skills:
      - Code samples for technical skills
      - Decision trees for complex workflows
      - Concrete examples with realistic user requests
      - References to scripts/templates/references as needed]
      
      ## Resources
      
      This skill includes example resource directories that demonstrate how to organize different types of bundled resources:
      
      ### scripts/
      Executable code (Python/Bash/etc.) that can be run directly to perform specific operations.
      
      **Examples from other skills:**
      - PDF skill: `fill_fillable_fields.py`, `extract_form_field_info.py` - utilities for PDF manipulation
      - DOCX skill: `document.py`, `utilities.py` - Python modules for document processing
      
      **Appropriate for:** Python scripts, shell scripts, or any executable code that performs automation, data processing, or specific operations.
      
      **Note:** Scripts may be executed without loading into context, but can still be read by Claude for patching or environment adjustments.
      
      ### references/
      Documentation and reference material intended to be loaded into context to inform Claude's process and thinking.
      
      **Examples from other skills:**
      - Product management: `communication.md`, `context_building.md` - detailed workflow guides
      - BigQuery: API reference documentation and query examples
      - Finance: Schema documentation, company policies
      
      **Appropriate for:** In-depth documentation, API references, database schemas, comprehensive guides, or any detailed information that Claude should reference while working.
      
      ### assets/
      Files not intended to be loaded into context, but rather used within the output Claude produces.
      
      **Examples from other skills:**
      - Brand styling: PowerPoint template files (.pptx), logo files
      - Frontend builder: HTML/React boilerplate project directories
      - Typography: Font files (.ttf, .woff2)
      
      **Appropriate for:** Templates, boilerplate code, document templates, images, icons, fonts, or any files meant to be copied or used in the final output.
      
      ---
      
      **Any unneeded directories can be deleted.** Not every skill requires all three types of resources.
      """
      
      EXAMPLE_SCRIPT = '''#!/usr/bin/env python3
      """
      Example helper script for {skill_name}
      
      This is a placeholder script that can be executed directly.
      Replace with actual implementation or delete if not needed.
      
      Example real scripts from other skills:
      - pdf/scripts/fill_fillable_fields.py - Fills PDF form fields
      - pdf/scripts/convert_pdf_to_images.py - Converts PDF pages to images
      """
      
      def main():
          print("This is an example script for {skill_name}")
          # TODO: Add actual script logic here
          # This could be data processing, file conversion, API calls, etc.
      
      if __name__ == "__main__":
          main()
      '''
      
      EXAMPLE_REFERENCE = """# Reference Documentation for {skill_title}
      
      This is a placeholder for detailed reference documentation.
      Replace with actual reference content or delete if not needed.
      
      Example real reference docs from other skills:
      - product-management/references/communication.md - Comprehensive guide for status updates
      - product-management/references/context_building.md - Deep-dive on gathering context
      - bigquery/references/ - API references and query examples
      
      ## When Reference Docs Are Useful
      
      Reference docs are ideal for:
      - Comprehensive API documentation
      - Detailed workflow guides
      - Complex multi-step processes
      - Information too lengthy for main SKILL.md
      - Content that's only needed for specific use cases
      
      ## Structure Suggestions
      
      ### API Reference Example
      - Overview
      - Authentication
      - Endpoints with examples
      - Error codes
      - Rate limits
      
      ### Workflow Guide Example
      - Prerequisites
      - Step-by-step instructions
      - Common patterns
      - Troubleshooting
      - Best practices
      """
      
      EXAMPLE_ASSET = """# Example Asset File
      
      This placeholder represents where asset files would be stored.
      Replace with actual asset files (templates, images, fonts, etc.) or delete if not needed.
      
      Asset files are NOT intended to be loaded into context, but rather used within
      the output Claude produces.
      
      Example asset files from other skills:
      - Brand guidelines: logo.png, slides_template.pptx
      - Frontend builder: hello-world/ directory with HTML/React boilerplate
      - Typography: custom-font.ttf, font-family.woff2
      - Data: sample_data.csv, test_dataset.json
      
      ## Common Asset Types
      
      - Templates: .pptx, .docx, boilerplate directories
      - Images: .png, .jpg, .svg, .gif
      - Fonts: .ttf, .otf, .woff, .woff2
      - Boilerplate code: Project directories, starter files
      - Icons: .ico, .svg
      - Data files: .csv, .json, .xml, .yaml
      
      Note: This is a text placeholder. Actual assets can be any file type.
      """
      
      
      def title_case_skill_name(skill_name):
          """Convert hyphenated skill name to Title Case for display."""
          return ' '.join(word.capitalize() for word in skill_name.split('-'))
      
      
      def init_skill(skill_name, path):
          """
          Initialize a new skill directory with template SKILL.md.
      
          Args:
              skill_name: Name of the skill
              path: Path where the skill directory should be created
      
          Returns:
              Path to created skill directory, or None if error
          """
          # Determine skill directory path
          skill_dir = Path(path).resolve() / skill_name
      
          # Check if directory already exists
          if skill_dir.exists():
              print(f"❌ Error: Skill directory already exists: {skill_dir}")
              return None
      
          # Create skill directory
          try:
              skill_dir.mkdir(parents=True, exist_ok=False)
              print(f"✅ Created skill directory: {skill_dir}")
          except Exception as e:
              print(f"❌ Error creating directory: {e}")
              return None
      
          # Create SKILL.md from template
          skill_title = title_case_skill_name(skill_name)
          skill_content = SKILL_TEMPLATE.format(
              skill_name=skill_name,
              skill_title=skill_title
          )
      
          skill_md_path = skill_dir / 'SKILL.md'
          try:
              skill_md_path.write_text(skill_content)
              print("✅ Created SKILL.md")
          except Exception as e:
              print(f"❌ Error creating SKILL.md: {e}")
              return None
      
          # Create resource directories with example files
          try:
              # Create scripts/ directory with example script
              scripts_dir = skill_dir / 'scripts'
              scripts_dir.mkdir(exist_ok=True)
              example_script = scripts_dir / 'example.py'
              example_script.write_text(EXAMPLE_SCRIPT.format(skill_name=skill_name))
              example_script.chmod(0o755)
              print("✅ Created scripts/example.py")
      
              # Create references/ directory with example reference doc
              references_dir = skill_dir / 'references'
              references_dir.mkdir(exist_ok=True)
              example_reference = references_dir / 'api_reference.md'
              example_reference.write_text(EXAMPLE_REFERENCE.format(skill_title=skill_title))
              print("✅ Created references/api_reference.md")
      
              # Create assets/ directory with example asset placeholder
              assets_dir = skill_dir / 'assets'
              assets_dir.mkdir(exist_ok=True)
              example_asset = assets_dir / 'example_asset.txt'
              example_asset.write_text(EXAMPLE_ASSET)
              print("✅ Created assets/example_asset.txt")
          except Exception as e:
              print(f"❌ Error creating resource directories: {e}")
              return None
      
          # Print next steps
          print(f"\n✅ Skill '{skill_name}' initialized successfully at {skill_dir}")
          print("\nNext steps:")
          print("1. Edit SKILL.md to complete the TODO items and update the description")
          print("2. Customize or delete the example files in scripts/, references/, and assets/")
          print("3. Run the validator when ready to check the skill structure")
      
          return skill_dir
      
      
      def main():
          if len(sys.argv) < 4 or sys.argv[2] != '--path':
              print("Usage: init_skill.py <skill-name> --path <path>")
              print("\nSkill name requirements:")
              print("  - Hyphen-case identifier (e.g., 'data-analyzer')")
              print("  - Lowercase letters, digits, and hyphens only")
              print("  - Max 40 characters")
              print("  - Must match directory name exactly")
              print("\nExamples:")
              print("  init_skill.py my-new-skill --path skills/public")
              print("  init_skill.py my-api-helper --path skills/private")
              print("  init_skill.py custom-skill --path /custom/location")
              sys.exit(1)
      
          skill_name = sys.argv[1]
          path = sys.argv[3]
      
          print(f"🚀 Initializing skill: {skill_name}")
          print(f"   Location: {path}")
          print()
      
          result = init_skill(skill_name, path)
      
          if result:
              sys.exit(0)
          else:
              sys.exit(1)
      
      
      if __name__ == "__main__":
          main()
      
    • package_skill.py 3.2 KB
      #!/usr/bin/env python3
      """
      Skill Packager - Creates a distributable .skill file of a skill folder
      
      Usage:
          python utils/package_skill.py <path/to/skill-folder> [output-directory]
      
      Example:
          python utils/package_skill.py skills/public/my-skill
          python utils/package_skill.py skills/public/my-skill ./dist
      """
      
      import sys
      import zipfile
      from pathlib import Path
      from quick_validate import validate_skill
      
      
      def package_skill(skill_path, output_dir=None):
          """
          Package a skill folder into a .skill file.
      
          Args:
              skill_path: Path to the skill folder
              output_dir: Optional output directory for the .skill file (defaults to current directory)
      
          Returns:
              Path to the created .skill file, or None if error
          """
          skill_path = Path(skill_path).resolve()
      
          # Validate skill folder exists
          if not skill_path.exists():
              print(f"❌ Error: Skill folder not found: {skill_path}")
              return None
      
          if not skill_path.is_dir():
              print(f"❌ Error: Path is not a directory: {skill_path}")
              return None
      
          # Validate SKILL.md exists
          skill_md = skill_path / "SKILL.md"
          if not skill_md.exists():
              print(f"❌ Error: SKILL.md not found in {skill_path}")
              return None
      
          # Run validation before packaging
          print("🔍 Validating skill...")
          valid, message = validate_skill(skill_path)
          if not valid:
              print(f"❌ Validation failed: {message}")
              print("   Please fix the validation errors before packaging.")
              return None
          print(f"✅ {message}\n")
      
          # Determine output location
          skill_name = skill_path.name
          if output_dir:
              output_path = Path(output_dir).resolve()
              output_path.mkdir(parents=True, exist_ok=True)
          else:
              output_path = Path.cwd()
      
          skill_filename = output_path / f"{skill_name}.skill"
      
          # Create the .skill file (zip format)
          try:
              with zipfile.ZipFile(skill_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
                  # Walk through the skill directory
                  for file_path in skill_path.rglob('*'):
                      if file_path.is_file():
                          # Calculate the relative path within the zip
                          arcname = file_path.relative_to(skill_path.parent)
                          zipf.write(file_path, arcname)
                          print(f"  Added: {arcname}")
      
              print(f"\n✅ Successfully packaged skill to: {skill_filename}")
              return skill_filename
      
          except Exception as e:
              print(f"❌ Error creating .skill file: {e}")
              return None
      
      
      def main():
          if len(sys.argv) < 2:
              print("Usage: python utils/package_skill.py <path/to/skill-folder> [output-directory]")
              print("\nExample:")
              print("  python utils/package_skill.py skills/public/my-skill")
              print("  python utils/package_skill.py skills/public/my-skill ./dist")
              sys.exit(1)
      
          skill_path = sys.argv[1]
          output_dir = sys.argv[2] if len(sys.argv) > 2 else None
      
          print(f"📦 Packaging skill: {skill_path}")
          if output_dir:
              print(f"   Output directory: {output_dir}")
          print()
      
          result = package_skill(skill_path, output_dir)
      
          if result:
              sys.exit(0)
          else:
              sys.exit(1)
      
      
      if __name__ == "__main__":
          main()
      
    • quick_validate.py 3.4 KB
      #!/usr/bin/env python3
      """
      Quick validation script for skills - minimal version
      """
      
      import sys
      import os
      import re
      import yaml
      from pathlib import Path
      
      def validate_skill(skill_path):
          """Basic validation of a skill"""
          skill_path = Path(skill_path)
      
          # Check SKILL.md exists
          skill_md = skill_path / 'SKILL.md'
          if not skill_md.exists():
              return False, "SKILL.md not found"
      
          # Read and validate frontmatter
          content = skill_md.read_text()
          if not content.startswith('---'):
              return False, "No YAML frontmatter found"
      
          # Extract frontmatter
          match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
          if not match:
              return False, "Invalid frontmatter format"
      
          frontmatter_text = match.group(1)
      
          # Parse YAML frontmatter
          try:
              frontmatter = yaml.safe_load(frontmatter_text)
              if not isinstance(frontmatter, dict):
                  return False, "Frontmatter must be a YAML dictionary"
          except yaml.YAMLError as e:
              return False, f"Invalid YAML in frontmatter: {e}"
      
          # Define allowed properties
          ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata'}
      
          # Check for unexpected properties (excluding nested keys under metadata)
          unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES
          if unexpected_keys:
              return False, (
                  f"Unexpected key(s) in SKILL.md frontmatter: {', '.join(sorted(unexpected_keys))}. "
                  f"Allowed properties are: {', '.join(sorted(ALLOWED_PROPERTIES))}"
              )
      
          # Check required fields
          if 'name' not in frontmatter:
              return False, "Missing 'name' in frontmatter"
          if 'description' not in frontmatter:
              return False, "Missing 'description' in frontmatter"
      
          # Extract name for validation
          name = frontmatter.get('name', '')
          if not isinstance(name, str):
              return False, f"Name must be a string, got {type(name).__name__}"
          name = name.strip()
          if name:
              # Check naming convention (hyphen-case: lowercase with hyphens)
              if not re.match(r'^[a-z0-9-]+$', name):
                  return False, f"Name '{name}' should be hyphen-case (lowercase letters, digits, and hyphens only)"
              if name.startswith('-') or name.endswith('-') or '--' in name:
                  return False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens"
              # Check name length (max 64 characters per spec)
              if len(name) > 64:
                  return False, f"Name is too long ({len(name)} characters). Maximum is 64 characters."
      
          # Extract and validate description
          description = frontmatter.get('description', '')
          if not isinstance(description, str):
              return False, f"Description must be a string, got {type(description).__name__}"
          description = description.strip()
          if description:
              # Check for angle brackets
              if '<' in description or '>' in description:
                  return False, "Description cannot contain angle brackets (< or >)"
              # Check description length (max 1024 characters per spec)
              if len(description) > 1024:
                  return False, f"Description is too long ({len(description)} characters). Maximum is 1024 characters."
      
          return True, "Skill is valid!"
      
      if __name__ == "__main__":
          if len(sys.argv) != 2:
              print("Usage: python quick_validate.py <skill_directory>")
              sys.exit(1)
          
          valid, message = validate_skill(sys.argv[1])
          print(message)
          sys.exit(0 if valid else 1)
  • SKILL.md 66.5 KB
    ---
    name: skill-creator
    description: Guide for creating effective skills for AI coding agents working with Azure SDKs and Microsoft Foundry services. Use when creating new skills or updating existing skills.
    ---
    
    # Skill Creator
    
    Guide for creating skills that extend AI agent capabilities, with emphasis on Azure SDKs and Microsoft Foundry.
    
    > **Required Context:** When creating SDK or API skills, users MUST provide the SDK package name, documentation URL, or repository reference for the skill to be based on.
    
    ## About Skills
    
    Skills are modular knowledge packages that transform general-purpose agents into specialized experts:
    
    1. **Procedural knowledge** — Multi-step workflows for specific domains
    2. **SDK expertise** — API patterns, authentication, error handling for Azure services
    3. **Domain context** — Schemas, business logic, company-specific patterns
    4. **Bundled resources** — Scripts, references, templates for complex tasks
    
    ---
    
    ## Core Principles
    
    ### 1. Concise is Key
    
    The context window is a shared resource. Challenge each piece: "Does this justify its token cost?"
    
    **For domain/procedural skills**: Agents are already capable. Only add what they don't already know.
    
    **For SDK/API skills**: Users MUST provide SDK package name, documentation URL, or repository reference. The skill cannot be created without this context.
    
    ### 2. Fresh Documentation First
    
    **Azure SDKs change constantly.** Skills should instruct agents to verify documentation:
    
    ```markdown
    ## Before Implementation
    
    Search `microsoft-docs` MCP for current API patterns:
    
    - Query: "[SDK name] [operation] python"
    - Verify: Parameters match your installed SDK version
    ```
    
    ### 3. Degrees of Freedom
    
    Match specificity to implementation constraints. High freedom when approaches vary; low freedom when precise execution is required:
    
    | Freedom    | When                             | Example          |
    | ---------- | -------------------------------- | ---------------- |
    | **High**   | Multiple valid approaches        | Text guidelines  |
    | **Medium** | Preferred pattern with variation | Pseudocode       |
    | **Low**    | Must be exact                    | Specific scripts |
    
    ### 4. Progressive Disclosure
    
    Skills load in three levels:
    
    1. **Metadata** (~100 words) — Always in context
    2. **SKILL.md body** (<5k words) — When skill triggers
    3. **References** (unlimited) — As needed
    
    **Keep SKILL.md under 500 lines.** Split into reference files when approaching this limit.
    
    ---
    
    ## Skill Structure
    
    **Quick reference:**
    
    ```
    skill-name/
    ├── SKILL.md (required)
    │   ├── YAML frontmatter (name, description)
    │   └── Markdown instructions
    └── Bundled Resources (optional)
        ├── scripts/      — Executable code
        ├── references/   — Documentation loaded as needed
        └── assets/       — Output resources (templates, images)
    ```
    
    For Azure SDK skills, follow the **Skill Section Order** below. For domain skills, use your judgment to organize logically.
    
    ### SKILL.md Essentials
    
    - **Frontmatter**: `name` and `description` (description triggers the skill)
    - **Body**: Keep under 500 lines; split large skills into reference files
    
    ### Bundled Resources (Optional)
    
    | Type          | When to Include                          | Examples                                                   |
    | ------------- | ---------------------------------------- | ---------------------------------------------------------- |
    | `scripts/`    | Reused code patterns                     | Auth setup, CLI scripts                                    |
    | `references/` | Feature deep-dives and overflow examples | `capabilities.md` index, `non-hero-scenarios.md`, API docs |
    | `assets/`     | Output templates                         | Boilerplate code, images                                   |
    
    ---
    
    ## Creating Azure SDK Skills
    
    When creating skills for Azure SDKs, follow these patterns consistently.
    
    ### Token Budget Guidelines (REQUIRED)
    
    Every Azure SDK skill MUST stay within these token limits:
    
    | Section                       | Target           | Absolute Max     |
    | ----------------------------- | ---------------- | ---------------- |
    | Installation + Env Vars       | 100 tokens       | 150              |
    | Authentication & Lifecycle    | 200 tokens       | 300              |
    | Core Workflow (1 example)     | 300 tokens       | 400              |
    | Feature Tables                | 200 tokens       | 300              |
    | Best Practices (6-8 items)    | 200 tokens       | 250              |
    | References (reference/ links) | 100 tokens       | 150              |
    | **Total SKILL.md**            | **~1100 tokens** | **~1500 tokens** |
    
    **Enforcement**:
    
    - Exceeding max limit → refactor into `/references/` subdirectories
    - When approaching 500 lines → move entire sections to reference files
    - Annotate with `<!-- Token Count: ~XXXX (target: 1100, max: 1500) -->` immediately below the skill's H1
    
    ---
    
    ### Reference Extraction Guide (REQUIRED)
    
    Decide what goes in SKILL.md vs. `/references/` using these signals:
    
    | Signal         | Move to `/references/`              | Keep in SKILL.md       |
    | -------------- | ----------------------------------- | ---------------------- |
    | Use frequency  | <20% of typical use                 | ~80%+ of workflows     |
    | Cognitive load | Advanced patterns, multiple options | Single happy path      |
    | Example length | >10 lines, multiple paths           | 1-5 lines, single path |
    
    **Content extraction rules:**
    
    - **Batch operations** → `/references/batch-operations.md`
    - **Error handling** (beyond try-except) → `/references/error-handling.md`
    - **Performance tuning** → `/references/performance.md`
    - **Alternative workflows** → `/references/workflows-comparison.md`
    - **Streaming/events** → `/references/streaming.md`
    - **Advanced auth** → `/references/auth-strategies.md`
    - **Tool integration** → `/references/tools.md`
    - **Breaking changes** → `/references/migration.md`
    
    **Decision:** Keep common case in SKILL.md, move edge cases to `/references/`.
    
    ---
    
    ### Core Workflow Discipline (REQUIRED)
    
    Every Azure SDK skill must clarify which workflow(s) it documents.
    
    **Case 1: Single clear "core workflow"** (majority of services)
    
    If one pattern handles ~80% of use cases:
    
    1. Designate it as the core workflow
    2. Show ONLY this workflow in SKILL.md (one complete, runnable example)
    3. Defer alternatives to `/references/`:
       - Batch operations → `/references/batch-operations.md`
       - Error handling → `/references/error-handling.md`
       - Performance tuning → `/references/performance.md`
       - Alternative workflows → `/references/workflows-comparison.md`
    
    **Example**: Azure Key Vault Secrets (core workflow: retrieve a secret using managed identity). Alternative authentication workflows in `/references/`: local development with `DefaultAzureCredential`, workload identity, and service-principal credentials (client secret or certificate).
    
    **Case 2: Multiple equally-valid "core workflows"** (e.g., authentication strategies, deployment targets)
    
    If no single pattern dominates:
    
    1. Include every hero scenario in SKILL.md, even when that means multiple equally valid workflows
    2. Show one complete, runnable example for each hero scenario in SKILL.md
    3. Use `/references/workflows-comparison.md` for trade-offs, secondary variations, and deeper context that would otherwise bloat the main file
    4. Do NOT treat valid alternatives as "advanced" when they are core to real usage — they're equally valid, just different contexts
    
    **Example**: Azure Identity SDK has several hero scenarios. Keep the primary local-development and production-safe credential flows in SKILL.md, then use `/references/credential-types.md` for deeper comparisons across `AzureCliCredential`, workload identity, service principal variants, and other secondary credential choices.
    
    **Decision rule**: If you're unsure, ask: "Would a user choosing the other approach call what I wrote wrong?" If yes, it's another hero scenario and belongs in SKILL.md. If no, it can be summarized and linked from `/references/`.
    
    ---
    
    ### Skill Section Order
    
    Follow this structure (based on existing Azure SDK skills):
    
    1. **Title** — `# SDK Name`
    2. **Installation** — `pip install`, `npm install`, etc.
    3. **Environment Variables** — Required configuration, with an inline comment explaining when it's required. If using `DefaultAzureCredential` in production, include `AZURE_TOKEN_CREDENTIALS` (set to `prod` or `<specific_credential>`)
    4. **Authentication & Lifecycle** — For Python skills, prefer `DefaultAzureCredential`: use it as-is for local development, and constrain it for production by setting `AZURE_TOKEN_CREDENTIALS` to `prod` (or a specific target credential name). A specific Microsoft Entra Token credential such as `ManagedIdentityCredential` or `WorkloadIdentityCredential` may be used directly instead. **For Python skills, this section MUST start with the standard callout block** (see [Required Authentication & Lifecycle Callout (Python)](#required-authentication--lifecycle-callout-python) below).
    5. **Core Workflow** — Minimal viable example (per core workflow discipline above)
    6. **Feature Tables** — Clients, methods, tools
    7. **Best Practices** — Numbered list
    8. **Reference Links** — Table linking to `/references/*.md` (for Azure SDK skills, include `capabilities.md` + `non-hero-scenarios.md`)
    
    ### Required Authentication & Lifecycle Callout (Python)
    
    > **Scope:** Python skills (`-py` suffix) only. Other languages may follow their own idioms.
    
    Every Python Azure SDK skill MUST open its `## Authentication & Lifecycle` section with the following callout block, **verbatim**, before any code samples. This makes the two non-negotiable rules visible to users before they read or copy any client setup code.
    
    ```markdown
    ## Authentication & Lifecycle
    
    > **🔑 Two rules apply to every code sample below:**
    >
    > 1. **Prefer `DefaultAzureCredential` for local development.** It works as-is with Azure CLI / VS Code / Developer CLI. For production, either constrain `DefaultAzureCredential` to production-safe credentials or use a specific credential directly. Avoid connection strings, account/API keys — they bypass Entra audit and rotation.
    >    - Local dev: `DefaultAzureCredential` works as-is.
    >    - Production: set `AZURE_TOKEN_CREDENTIALS=prod` (or `AZURE_TOKEN_CREDENTIALS=<specific_credential>`) to constrain the credential chain to production-safe credentials.
    > 2. **Wrap every client in a context manager** so HTTP transports, sockets, and token caches are released deterministically:
    >    - Sync: `with <Client>(...) as client:`
    >    - Async: `async with <Client>(...) as client:` **and** `async with DefaultAzureCredential() as credential:` (from `azure.identity.aio`)
    >
    > Snippets may abbreviate this setup, but production code should always follow both rules.
    ```
    
    **Placement rules:**
    
    - Insert immediately under the `## Authentication & Lifecycle` heading, before the first code sample.
    - Do not paraphrase or restructure the wording — the consistency across skills is the point.
    - If the SDK does not support Entra ID at all (rare — e.g. some legacy speech REST endpoints, websocket APIs that require subscription keys), keep rule #2 (context managers) and replace rule #1 with a single sentence noting the SDK requires API-key auth and explaining why Entra is not yet available.
    - If the SDK is async-only (e.g. `azure-ai-voicelive`), keep both rules but show only the async form in the bullets.
    - Skip the callout entirely for non-Azure Python skills with no client lifecycle (e.g. `pydantic-models-py`).
    
    **Code sample enforcement.** Every client construction in the skill body must demonstrate both rules:
    
    - Show `with` / `async with` on every client instantiation in usage examples (not just the auth section).
    - Show `DefaultAzureCredential` in the primary auth example. **Do not delete API-key examples for SDKs where keys are still officially supported** — many existing users (especially in regulated environments still completing their Entra rollout) need a copy-pastable working sample. Demote the keyed snippet into a clearly-labeled `### Legacy: API Key (existing keyed deployments)` subsection placed _after_ the primary `DefaultAzureCredential` block in the same `## Authentication & Lifecycle` section. Include a one-line note that new code should use `DefaultAzureCredential` and that the keyed path is for existing deployments. Also add the `<SERVICE>_KEY` env var back to the Environment Variables block with a `# Only required for the legacy API-key auth path below` comment.
    - A handful of services have key-specific quirks worth calling out in the Legacy subsection (e.g. `azure-ai-translation-text` requires a `region=` parameter when using a key against the global endpoint, because token-credential auth requires a custom subdomain endpoint). Surface these in the demoted block rather than dropping the example.
    - For async examples, wrap `DefaultAzureCredential` from `azure.identity.aio` in `async with credential:` alongside the client.
    
    ### Authentication Pattern (All Languages)
    
    For local development, use `DefaultAzureCredential` which supports multiple auth methods. For production, use a specific credential type or configure `DefaultAzureCredential` with environment variable `AZURE_TOKEN_CREDENTIALS` set to `prod` or specify the target credential.
    
    If configuring a Rust skill, use `DeveloperToolsCredential` for local development and `ManagedIdentityCredential` for production. The Rust SDK does not support `DefaultAzureCredential`, so explicitly use the appropriate credential in each environment.
    
    ```python
    # Python — note: client is wrapped in `with` for deterministic cleanup
    from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
    # Local dev: DefaultAzureCredential works as-is.
    credential = DefaultAzureCredential()
    # Production alternative: constrain DefaultAzureCredential with AZURE_TOKEN_CREDENTIALS.
    # credential = DefaultAzureCredential(require_envvar=True)
    # Or use a specific credential directly in production:
    # See https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python#credential-classes
    # credential = ManagedIdentityCredential()
    with ServiceClient(endpoint, credential) as client:
        client.do_thing()
    ```
    
    ```csharp
    // C#
    using Azure.Identity;
    
    // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
    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();
    var client = new ServiceClient(new Uri(endpoint), credential);
    ```
    
    ```java
    // Java
    import com.azure.identity.AzureIdentityEnvVars;
    import com.azure.identity.DefaultAzureCredentialBuilder;
    import com.azure.identity.ManagedIdentityCredential;
    import com.azure.identity.ManagedIdentityCredentialBuilder;
    
    // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
    TokenCredential credential = new DefaultAzureCredentialBuilder()
        .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
        .build();
    // Or use a specific credential directly in production:
    // See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes
    // TokenCredential credential = new ManagedIdentityCredentialBuilder().build();
    ServiceClient client = new ServiceClientBuilder()
        .endpoint(endpoint)
        .credential(credential)
        .buildClient();
    ```
    
    ```typescript
    // TypeScript
    import {
      DefaultAzureCredential,
      ManagedIdentityCredential,
    } from "@azure/identity";
    // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
    const credential = new DefaultAzureCredential({
      requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"],
    });
    // Or use a specific credential directly in production:
    // See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
    // const credential = new ManagedIdentityCredential();
    const client = new ServiceClient(endpoint, credential);
    ```
    
    ```go
    // Go
    import (
      "context"
    
      "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
      "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
    )
    
    ctx := context.Background()
    
    // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
    cred, err := azidentity.NewDefaultAzureCredential(nil)
    if err != nil {
      panic(err)
    }
    
    // Or use a specific credential directly in production:
    // cred, err := azidentity.NewManagedIdentityCredential(nil)
    
    client, err := azblob.NewClient("https://<account>.blob.core.windows.net/", cred, nil)
    if err != nil {
      panic(err)
    }
    
    _ = client
    _ = ctx
    ```
    
    ```rust
    // Rust
    use azure_identity::DeveloperToolsCredential;
    use azure_storage_blob::BlobServiceClient;
    
    let credential = DeveloperToolsCredential::new(); // Local dev
    let client = BlobServiceClient::new(
        "https://<account>.blob.core.windows.net/",
        credential,
        None,
    )?;
    ```
    
    **Never hardcode credentials. Use environment variables.**
    
    ### Anti-Patterns: What NOT to Do (REQUIRED Reading)
    
    **These patterns cause bloat and inefficiency. Every skill author must review this section before writing.**
    
    #### Anti-Pattern 1: "Exhaustive API Reference"
    
    - ❌ **Don't**: List all 50 SDK methods in a feature table with code samples for every variant
    - ✅ **Do**: Show 3-5 core methods in a table; link to official Azure API reference for exhaustive list
    - **Token cost**: Listing all methods + examples = 400-600 tokens wasted
    - **User impact**: Overwhelming cognitive load; users don't know what to use
    
    #### Anti-Pattern 2: "Multiple Ways to Solve One Problem"
    
    - ❌ **Don't**: "Here's approach A, B, C, and D to paginate results" in the main body
    - ✅ **Do**: "Use `ItemPaged` for sync pagination" (primary example); link alternatives to `/references/`
    - **Token cost**: Each alternate approach = 50-100 tokens; 5 approaches = skill becomes inefficient
    - **User impact**: Decision paralysis; users re-read everything
    
    #### Anti-Pattern 3: "Beginner + Intermediate + Advanced in One Skill"
    
    - ❌ **Don't**: Skill that goes from "what is a client?" to "custom retry policies" to "circuit breaker patterns"
    - ✅ **Do**: Core workflow covers 80% use case; advanced patterns in `/references/`
    - **Token cost**: Every skill level adds 200-300 tokens; three levels = 600-900 extra tokens
    - **User impact**: Experts bored, beginners overwhelmed; nobody gets what they need
    
    #### Anti-Pattern 4: "Restating Official Documentation"
    
    - ❌ **Don't**: "The CosmosClient constructor takes an endpoint (string) and credential (TokenCredential). The endpoint identifies the Azure Cosmos resource..."
    - ✅ **Do**: Show code: `client = CosmosClient(endpoint, credential)`. Link to official docs: `microsoft-docs` MCP.
    - **Token cost**: Verbose explanation = 50-100 tokens per parameter; large APIs waste 300+ tokens
    - **User impact**: Redundant; official docs are authoritative, skill should show usage not repeat them
    
    #### Anti-Pattern 5: "Verbose Explanation When Example Suffices"
    
    - ❌ **Don't**: "To create a client, you first instantiate the class using the constructor, passing the endpoint and credential parameters. The endpoint is a string that identifies your resource..."
    - ✅ **Do**: Show code immediately: `with CosmosClient(endpoint, credential) as client:`
    
    ---
    
    ### Efficiency Validation (REQUIRED - Phase 2)
    
    **During authoring, validate skill efficiency manually, then run the Vally eval if the skill has one under `tests/scenarios/<skill-name>/vally/`.**
    
    **1. Measure token count:**
    
    Use a token counter or model playground to measure each section. Compare to the Token Budget Guidelines targets above. If any section exceeds max, move content to `/references/`.
    
    **2. Run anti-pattern checklist:**
    
    - [ ] No exhaustive API reference (show 3-5 core methods, not 50)
    - [ ] No multiple solutions to one problem in SKILL.md
    - [ ] No beginner+intermediate+advanced mixed
    - [ ] No restating official docs (code first, link to microsoft-docs)
    - [ ] No verbose prose (examples first, minimal text)
    
    **3. Example count audit:**
    
    - [ ] 1 complete example per hero scenario / core workflow documented in SKILL.md. For Python SDKs that support both sync and async, the paired sync + async examples for the same workflow count as one workflow, not two.
    - [ ] Feature table includes 3-5 core methods (not comprehensive API)
    - [ ] Max 1 example per best practice bullet
    
    **4. Frontmatter validation:**
    
    - [ ] `name` matches `.github/skills/<name>/SKILL.md`
    - [ ] `description` includes trigger keywords
    - [ ] `description` is concise (~200 chars is a good target; schema max is 1,024 chars)
    - [ ] If included, optional `benchmark_tokens_*` and `benchmark_quality_*` metadata fields are flat strings under `metadata`
    
    **4b. Authentication guidance validation** (critical for all credentials):
    
    - [ ] If skill uses Azure Identity credentials, verify guidance against the current official credential docs for that language/package (Microsoft Learn where available; otherwise the upstream SDK repo or package docs)
    - [ ] For Python skills, development guidance may recommend `DefaultAzureCredential` (supports multiple dev credential types)
    - [ ] For Python skills, production guidance: `DefaultAzureCredential` alone (unconstrained) is not sufficient; require either `AZURE_TOKEN_CREDENTIALS=prod` (or a specific target credential) to constrain the chain, or a specific credential (e.g., `ManagedIdentityCredential`) used directly
    - [ ] For Rust skills, development/production guidance reflects the actual supported credentials (`DeveloperToolsCredential` for local dev; a specific production credential such as `ManagedIdentityCredential` for production)
    - [ ] Link to `/references/auth-strategies.md` or official docs for production credential selection
    
    **4c. Run Vally lint/eval (if the skill has a spec under `tests/scenarios/<skill-name>/vally/`):**
    
    ```bash
    # If the eval spec uses the shared Rust custom grader plugin, build it first.
    (cd tests/scenarios/_shared/vally/grader-plugins/rust-cargo-build-failure && npm install && npm run build)
    
    vally lint --eval-spec tests/scenarios/<skill-name>/vally/eval.yaml \
      --grader-plugin tests/scenarios/_shared/vally/grader-plugins/rust-cargo-build-failure \
      --strict
    
    vally eval --eval-spec tests/scenarios/<skill-name>/vally/eval.yaml \
      --grader-plugin tests/scenarios/_shared/vally/grader-plugins/rust-cargo-build-failure
    ```
    
    - [ ] `vally lint` passes with no errors
    - [ ] `vally eval` passes (no error-severity findings) when `COPILOT_TOKEN` is available; otherwise lint-only is acceptable, matching the [`Vally Evaluation`](../../workflows/vally-evaluation.yml) workflow behavior
    - [ ] Skills without a `vally/` spec skip this step — it is optional per skill, not required for every skill
    
    **5. Spot check:**
    
    - [ ] Can a user copy the core workflow and run it immediately?
    - [ ] Do all examples follow best practices (context managers, appropriate credentials)?
    - [ ] Are all environment variables documented?
    
    **Output:** After validation, annotate the skill header with measured token count:
    
    ```markdown
    # Azure Service SDK
    
    <!-- Token Count: ~1180 (target: 1100, max: 1500) -->
    ```
    
    ---
    
    ### Standard Verb Patterns
    
    Azure SDKs use consistent verbs across all languages:
    
    | Verb     | Behavior                     |
    | -------- | ---------------------------- |
    | `create` | Create new; fail if exists   |
    | `upsert` | Create or update             |
    | `get`    | Retrieve; error if missing   |
    | `list`   | Return collection            |
    | `delete` | Succeed even if missing      |
    | `begin`  | Start long-running operation |
    
    ### Language-Specific Patterns
    
    See `references/azure-sdk-patterns.md` for detailed patterns including:
    
    - **Python**: `ItemPaged`, `LROPoller`, context managers, Sphinx docstrings. When the SDK provides both sync and async clients, present both forms as first-class options; do not express a preference for either. When the SDK is sync-only or async-only, document the available mode only. Do not mix sync and async within a single code example. Always show `with` / `async with` context managers.
    - **.NET**: `Response<T>`, `Pageable<T>`, `Operation<T>`, mocking support
    - **Java**: Builder pattern, `PagedIterable`/`PagedFlux`, Reactor types
    - **TypeScript**: `PagedAsyncIterableIterator`, `AbortSignal`, browser considerations
    - **Go**: `context.Context` as first arg, `runtime.Pager[T]` via `New*Pager()` + `More()/NextPage(ctx)`, `runtime.Poller[T]` via `Begin*` + `PollUntilDone(ctx, nil)`, `to.Ptr(...)` helpers, and typed `*azcore.ResponseError`
    - **Rust**: Installation via `cargo add`, dependency rule for `azure_core`, `Response<T>`, `Pager<T>`, `RequestContent::from()`, `.into_model()`, explicit credential types, RBAC roles for Entra ID authentication
    
    ### Required Best Practices in Every Skill (User-Facing)
    
    #### Python, .NET, Java, TypeScript, and Go languages
    
    **These two rules are not just authoring conventions for the skill itself — they MUST be explicitly written into every generated skill's `## Best Practices` section so end users who follow the skill apply them in their own code.**
    
    Add both items verbatim (adapted only for language/SDK specifics) as the **first two items** of the Best Practices list. Do not assume users will infer them from examples.
    
    **Standard wording (Python; adapt for other languages):**
    
    ```markdown
    1. **Do not mix sync and async clients in the same call path.** Use either `azure.xxx` sync clients or `azure.xxx.aio` async clients within a single call path — do not combine both.
    2. **Always use context managers for clients and async credentials.** Wrap every client in `with Client(...) as client:` (sync) or `async with Client(...) as client:` (async). For async `DefaultAzureCredential` from `azure.identity.aio`, also use `async with credential:` so tokens and transports are cleaned up.
    3. **Use `DefaultAzureCredential`** for code that runs locally. For code that runs in Azure, either constrain `DefaultAzureCredential` with `AZURE_TOKEN_CREDENTIALS=prod` (or a specific target credential) or use a specific token credential directly (e.g. `ManagedIdentityCredential`, `WorkloadIdentityCredential`).
    ```
    
    **Variants to apply when the SDK shape differs:**
    
    | Skill type                                                                    | Adjust item #1 to                                                                                                                   | Adjust item #2 to                                                                                                                                                                                                              |
    | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
    | Async-only SDK (e.g. voicelive)                                               | "This SDK is async-only; use the `.aio` namespace throughout."                                                                      | keep standard                                                                                                                                                                                                                  |
    | Framework guidance that is async-oriented (for example some agent frameworks) | "Use the framework's documented async patterns where required, but do not claim async is globally preferred for Azure Python SDKs." | keep standard                                                                                                                                                                                                                  |
    | Provider-pattern (OpenTelemetry exporters/distro)                             | keep standard                                                                                                                       | "Call `provider.shutdown()` / `flush()` at process exit to flush telemetry — providers are not context managers."                                                                                                              |
    | REST-over-httpx skills                                                        | keep standard                                                                                                                       | "Use `with httpx.Client(...) as client:` (sync) or `async with httpx.AsyncClient(...) as client:` (async) so connections pool and close deterministically."                                                                    |
    | Identity skill                                                                | keep standard                                                                                                                       | "Use credentials as context managers (`with DefaultAzureCredential() as credential:`) when they own token caches / HTTP transports you want cleaned up; for async, use `async with` on credentials from `azure.identity.aio`." |
    | FastAPI (non-Azure)                                                           | "Pick `def` or `async def` per endpoint based on whether you call async I/O; do not mix sync and blocking calls in one handler."    | "Manage long-lived resources (DB pools, HTTP clients) in `lifespan` and inject via `Depends`; use `with`/`async with` for per-request resources."                                                                              |
    | Pure model/schema skill (no I/O, e.g. pydantic)                               | **skip both** — not applicable                                                                                                      | **skip**                                                                                                                                                                                                                       |
    
    **Enforcement in code examples.** Every code example inside the skill must itself obey both rules, so the skill demonstrates what it prescribes:
    
    - Do not interleave sync and async calls within a single example. When the SDK provides both sync and async clients, show each mode in its own complete, self-contained example — a `### Sync` subsection and an `### Async` subsection — giving both equal prominence. When the SDK is sync-only or async-only, show only the available mode.
    - Every client instantiation in every example must be wrapped in `with` / `async with`. The only permitted exception is the mandatory Authentication snippet (which illustrates the credential + client construction pattern) and framework lifespan patterns where a client is owned by the app (e.g. FastAPI `lifespan`).
    - When async credentials from `azure.identity.aio` appear in an example, wrap them in `async with credential:` alongside the client.
    
    #### Rust Language
    
    **These rules MUST be explicitly written into every Rust skill's `## Best Practices` section as the first items:**
    
    1. **Use `cargo add` to manage dependencies, never edit `Cargo.toml` directly.** Always use `cargo add <crate>` or `cargo remove <crate>` instead of manually modifying the manifest file. Official crates are published on crates.io and should be added via cargo.
    
    2. **Add `azure_core` to `Cargo.toml` only when you import `azure_core` types directly.** If your code imports types like `azure_core::http::Url`, `azure_core::http::RequestContent`, or `azure_core::error::ErrorKind`, explicitly add `azure_core` to your dependencies. If you only use types re-exported by service crates (e.g., via `use azure_storage_blob::BlobClient`), a direct `azure_core` dependency is optional.
    
    3. **Use `DeveloperToolsCredential` for local development and `ManagedIdentityCredential` for production.** The Rust SDK does not support `DefaultAzureCredential`, so explicitly use the appropriate credential in each environment.
    
    4. **Use `RequestContent::from()` to wrap upload data.** When uploading data (e.g., blobs), wrap the content in `RequestContent::from(your_data)` to ensure proper handling by the SDK.
    
    5. **Assign appropriate RBAC roles for Entra ID auth.** For production authentication using Entra ID, ensure the identity has the necessary RBAC role assigned (e.g., "Storage Blob Data Contributor" for blob write access).
    
    6. **Always verify package versions using crates.io.** Before using a package, check its version on [crates.io](https://crates.io/) to ensure you are using a stable and supported release.
    
    7. **Future-proof `#[non_exhaustive]` model structs and enums.** Azure Rust SDK request/response models are frequently `#[non_exhaustive]`. For **externally constructible** structs that also derive `Default`, end the initializer with `..Default::default()` (even if every currently known field is set), suppressing the lint locally with `#[allow(clippy::needless_update)]` when needed. For **truly `#[non_exhaustive]`** structs (where Rust forbids external struct literals, producing E0639), use the provided constructor or builder, or construct a default value first and then mutate the fields you need. When matching an SDK enum, include a wildcard (`_`) arm so future service-added variants do not break the match. If a skill documents model construction, its code examples MUST demonstrate this pattern. See `references/azure-sdk-patterns.md` (Model Types) for the full example.
    
    ### Example Effective Skills (Benchmark Only Structure-Compliant Skills)
    
    **Only benchmark Azure SDK skills that already use the required `references/` layout** (`references/capabilities.md` plus `references/non-hero-scenarios.md`). Older skills that predate that structure can still be useful for style ideas, but do not mirror them directly until they are brought into compliance.
    
    **A valid benchmark skill should**:
    
    1. Stay at or under the 1,500-token absolute max (see Token Budget Guidelines above)
    2. Cover the hero workflow (CRUD or primary operations), not every feature variant
    3. Show 1-2 examples per concept, not 3-5
    4. Use tables for API summary (credential types, RBAC roles, client hierarchy)
    5. Link to official docs via `microsoft-docs` MCP instead of duplicating
    6. Move advanced patterns to `/references/`
    7. Include `references/capabilities.md` and `references/non-hero-scenarios.md`
    
    **Before writing your skill**: Apply the checklist above directly, then mirror only the structure patterns that fit your use case.
    
    ---
    
    ### Handling Deprecated or Rebranded SDKs
    
    When an Azure SDK has been deprecated or rebranded, update skills to guide users toward the current package while maintaining backward compatibility:
    
    **1. Add a migration notice at the top of the skill:**
    
    ```markdown
    > **⚠️ MIGRATION NOTICE**: The [Old Service Name] has been rebranded to **[New Service Name]**. While the package `old-package-name` remains available for compatibility, **new projects should use `new-package-name`** which provides the latest features and updates.
    >
    > **For new projects**: Use the `new-package-name` package instead.
    >
    > **This skill remains valid** for existing projects using `old-package-name`, but be aware you're using the legacy package name. The API patterns shown here are compatible with both packages.
    ```
    
    **2. Show both installation options:**
    
    ```markdown
    ## Installation
    
    ### Legacy Package (Old Name)
    
    \`\`\`xml
    <dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-old-package</artifactId>
    <version>4.2.0</version>
    </dependency>
    \`\`\`
    
    ### Recommended Package (New Name)
    
    **For new projects, use the rebranded package:**
    
    \`\`\`xml
    <dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-new-package</artifactId>
    <version>1.0.0</version>
    </dependency>
    \`\`\`
    
    > **Note**: The API patterns in this skill apply to both packages. Replace package names and imports as needed when using `azure-new-package`.
    ```
    
    **3. When to create a new skill vs. update existing:**
    
    - **Update existing skill** if the API is largely compatible (same or similar class/method names)
    - **Create new skill + migration guide** if the API changed significantly (use `references/migration.md`)
    - **Always cross-reference** between old and new skills
    
    **Examples:**
    
    - `azure-ai-formrecognizer-java` → `azure-ai-documentintelligence` (rebranded service)
    - `azure-communication-callingserver-java` → `azure-communication-callautomation` (deprecated, with migration guide)
    
    ### Example: Azure SDK Skill Structure
    
    ```markdown
    ---
    name: skill-creator
    description: |
      Azure AI Example SDK for Python. Use for [specific service features].
      Triggers: "example service", "create example", "list examples".
    ---
    
    # Azure AI Example SDK
    
    ## Installation
    
    \`\`\`bash
    pip install azure-ai-example
    \`\`\`
    
    ## Environment Variables
    
    \`\`\`bash
    AZURE_EXAMPLE_ENDPOINT=https://<resource>.example.azure.com
    AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
    \`\`\`
    
    ## Authentication & Lifecycle
    
    > **🔑 Two rules apply to every code sample below:**
    >
    > 1. **Prefer `DefaultAzureCredential` for local development.** It works as-is with Azure CLI / VS Code / Developer CLI. For production, either constrain `DefaultAzureCredential` to production-safe credentials or use a specific credential directly. Avoid connection strings, account/API keys — they bypass Entra audit and rotation.
    >    - Local dev: `DefaultAzureCredential` works as-is.
    >    - Production: set `AZURE_TOKEN_CREDENTIALS=prod` (or `AZURE_TOKEN_CREDENTIALS=<specific_credential>`) to constrain the credential chain to production-safe credentials.
    > 2. **Wrap every client in a context manager** so HTTP transports, sockets, and token caches are released deterministically:
    >    - Sync: `with <Client>(...) as client:`
    >    - Async: `async with <Client>(...) as client:` **and** `async with DefaultAzureCredential() as credential:` (from `azure.identity.aio`)
    >
    > Snippets may abbreviate this setup, but production code should always follow both rules.
    
    \`\`\`python
    from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
    from azure.ai.example import ExampleClient
    
    # Local dev: DefaultAzureCredential works as-is.
    credential = DefaultAzureCredential()
    
    # Production alternative: constrain DefaultAzureCredential with AZURE_TOKEN_CREDENTIALS.
    # credential = DefaultAzureCredential(require_envvar=True)
    
    # Or use a specific credential directly in production:
    
    # See https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python#credential-classes
    
    # credential = ManagedIdentityCredential()
    
    with ExampleClient(
    endpoint=os.environ["AZURE_EXAMPLE_ENDPOINT"],
    credential=credential,
    ) as client:
    item = client.get_item("example")
    \`\`\`
    
    ## Core Workflow
    
    \`\`\`python
    with ExampleClient(endpoint=endpoint, credential=credential) as client: # Create
    item = client.create_item(name="example", data={...})
    
        # List (pagination handled automatically)
        for item in client.list_items():
            print(item.name)
    
        # Long-running operation
        poller = client.begin_process(item.id)
        result = poller.result()
    
        # Cleanup
        client.delete_item(item.id)
    
    \`\`\`
    
    ## Reference Files
    
    | File                                                                 | Contents                                               |
    | -------------------------------------------------------------------- | ------------------------------------------------------ |
    | [references/capabilities.md](references/capabilities.md)             | Capability index (hero coverage + links to deep-dives) |
    | [references/non-hero-scenarios.md](references/non-hero-scenarios.md) | Concrete non-hero examples                             |
    | [references/tools.md](references/tools.md)                           | Tool integrations                                      |
    | [references/streaming.md](references/streaming.md)                   | Event streaming patterns                               |
    ```
    
    ---
    
    ## Skill Creation Process
    
    1. **Gather SDK Context** — User provides SDK/API reference (REQUIRED)
    2. **Understand** — Research SDK patterns from official docs
    3. **Plan** — Identify reusable resources and product area category
    4. **Create** — Write SKILL.md in `.github/skills/<skill-name>/`
    5. **Categorize** — Create symlink in `skills/<language>/<category>/`
    6. **Test** — Create acceptance criteria and test scenarios
    7. **Document** — Update README.md skill catalog
    8. **Iterate** — Refine based on real usage
    
    ### Step 1: Gather SDK Context (REQUIRED)
    
    **Before creating any SDK skill, the user MUST provide:**
    
    | Required                  | Example                                                   | Purpose                  |
    | ------------------------- | --------------------------------------------------------- | ------------------------ |
    | **SDK Package**           | `azure-ai-agents`, `Azure.AI.OpenAI`, `azblob`            | Identifies the exact SDK |
    | **Documentation URL**     | `https://learn.microsoft.com/en-us/azure/ai-services/...` | Primary source of truth  |
    | **Repository** (optional) | `Azure/azure-sdk-for-python`, `Azure/azure-sdk-for-go`    | For code patterns        |
    
    **Prompt the user if not provided:**
    
    ```
    To create this skill, I need:
    1. The SDK package name (e.g., azure-ai-projects)
    2. The Microsoft Learn documentation URL or GitHub repo
    3. The target language (py/dotnet/ts/java/go)
    ```
    
    **Search official docs first:**
    
    ```bash
    # Use microsoft-docs MCP to get current API patterns
    # Query: "[SDK name] [operation] [language]"
    # Verify: Parameters match the latest SDK version
    ```
    
    ### Step 2: Understand the Skill
    
    Gather concrete examples:
    
    - "What SDK operations should this skill cover?"
    - "What triggers should activate this skill?"
    - "What errors do developers commonly encounter?"
    
    | Example Task               | Reusable Resource              |
    | -------------------------- | ------------------------------ |
    | Same auth code each time   | Code example in SKILL.md       |
    | Complex streaming patterns | `references/streaming.md`      |
    | Tool configurations        | `references/tools.md`          |
    | Error handling patterns    | `references/error-handling.md` |
    
    ### Step 3: Plan Product Area Category
    
    Skills are organized by **language** and **product area** in the `skills/` directory via symlinks.
    
    **Product Area Categories:**
    
    | Category      | Description                             | Examples                                     |
    | ------------- | --------------------------------------- | -------------------------------------------- |
    | `foundry`     | AI Foundry, agents, projects, inference | `azure-ai-agents-py`, `azure-ai-projects-py` |
    | `data`        | Storage, Cosmos DB, Tables, Data Lake   | `azure-cosmos-py`, `azure-storage-blob-py`   |
    | `messaging`   | Event Hubs, Service Bus, Event Grid     | `azure-eventhub-py`, `azure-servicebus-py`   |
    | `monitoring`  | OpenTelemetry, App Insights, Query      | `azure-monitor-opentelemetry-py`             |
    | `identity`    | Authentication, DefaultAzureCredential  | `azure-identity-py`                          |
    | `security`    | Key Vault, secrets, keys, certificates  | `azure-keyvault-py`                          |
    | `integration` | API Management, App Configuration       | `azure-appconfiguration-py`                  |
    | `compute`     | Batch, ML compute                       | `azure-compute-batch-java`                   |
    | `container`   | Container Registry, ACR                 | `azure-containerregistry-py`                 |
    
    **Determine the category** based on:
    
    1. Azure service family (Storage → `data`, Event Hubs → `messaging`)
    2. Primary use case (AI agents → `foundry`)
    3. Existing skills in the same service area
    
    ### Step 4: Create the Skill
    
    **Location:** `.github/skills/<skill-name>/SKILL.md`
    
    **Naming convention:**
    
    - `azure-<service>-<subservice>-<language>`
    - Examples: `azure-ai-agents-py`, `azure-cosmos-java`, `azure-storage-blob-ts`, `azure-storage-blob-go`
    - For Go skills in documentation prose, use the short package name (for example `azblob`).
    - Use the full module import path only in code/import examples (for example `github.com/Azure/azure-sdk-for-go/sdk/storage/azblob`).
    
    **For Azure SDK skills:**
    
    1. Search `microsoft-docs` MCP for current API patterns
    2. Verify against installed SDK version
    3. Follow the section order above
    4. Include cleanup code in examples
    5. Add feature comparison tables
    
    **Write bundled resources first**, then SKILL.md.
    
    **Quality assurance before finalizing:**
    
    1. Measure section token counts as you write (use model playground token counter)
    2. Compare to Token Budget Guidelines targets
    3. Validate against anti-patterns checklist (see Anti-Patterns section)
    4. Extract to `/references/` if section exceeds max tokens
    5. Run Efficiency Validation checklist, including `vally lint`/`vally eval` if the skill has a spec (see Efficiency Validation)
    6. Optionally add `benchmark_tokens_*` and `benchmark_quality_*` fields under the frontmatter's `metadata` mapping (flat string values)
    7. Add token count comment to skill header for future maintenance
    
    **Frontmatter (Enhanced with Benchmarking Metadata):**
    
    ```yaml
    ---
    name: azure-service-py
    description: |
      Azure Service SDK for Python. Use for [specific features].
      Triggers: "service name", "create resource", "specific operation".
    metadata:
      benchmark_tokens_estimated: "1180"
      benchmark_tokens_target: "1100"
      benchmark_tokens_max: "1500"
      benchmark_quality_single_core_workflow: "true"
      benchmark_quality_examples_focused: "true"
      benchmark_quality_no_prose_bloat: "true"
      benchmark_quality_anti_patterns_checked: "true"
    ---
    ```
    
    **Metadata fields:** (all values are strings, per the Agent Skills `metadata` spec — string keys mapped to string values)
    
    - `benchmark_tokens_estimated` — Actual measured token count
    - `benchmark_tokens_target` — Target efficiency (typically 1100)
    - `benchmark_tokens_max` — Absolute ceiling (1500; split if exceeded)
    - `benchmark_quality_*` — Individual anti-pattern checks, each a `"true"`/`"false"` string (e.g., `benchmark_quality_single_core_workflow`)
    
    ### Step 5: Categorize with Symlinks
    
    After creating the skill in `.github/skills/`, create a symlink in the appropriate category:
    
    ```bash
    # Pattern: skills/<language>/<category>/<short-name> -> ../../../.github/skills/<full-skill-name>
    
    # Example for azure-ai-agents-py in python/foundry:
    cd skills/python/foundry
    ln -s ../../../.github/skills/azure-ai-agents-py agents
    
    # Example for azure-cosmos-db-py in python/data:
    cd skills/python/data
    ln -s ../../../.github/skills/azure-cosmos-db-py cosmos-db
    
    # Example for azure-storage-blob-go in go/data:
    cd skills/go/data
    ln -s ../../../.github/skills/azure-storage-blob-go blob
    ```
    
    **Symlink naming:**
    
    - Use short, descriptive names (e.g., `agents`, `cosmos`, `blob`)
    - Remove the `azure-` prefix and language suffix
    - Match existing patterns in the category
    
    **Verify the symlink:**
    
    ```bash
    ls -la skills/python/foundry/agents
    # Should show: agents -> ../../../.github/skills/azure-ai-agents-py
    ```
    
    ### Step 6: Create Tests
    
    **Every skill MUST have acceptance criteria and test scenarios.**
    
    #### 6.1 Create Acceptance Criteria
    
    **Location:** `tests/scenarios/<skill-name>/acceptance-criteria.md`
    
    > Keep acceptance criteria in the `tests/` tree (never beside `SKILL.md` inside the skill folder).
    
    **Source materials** (in priority order):
    
    1. Official Microsoft Learn docs (via `microsoft-docs` MCP)
    2. SDK source code from the repository
    3. Existing reference files in the skill
    
    **Format:**
    
    ```markdown
    # Acceptance Criteria: <skill-name>
    
    **SDK**: `package-name`
    **Repository**: https://github.com/Azure/azure-sdk-for-<language>
    **Purpose**: Skill testing acceptance criteria
    
    ---
    
    ## 1. Correct Import Patterns
    
    ### 1.1 Client Imports
    
    #### ✅ CORRECT: Main Client
    
    \`\`\`python
    from azure.ai.mymodule import MyClient
    from azure.identity import DefaultAzureCredential
    \`\`\`
    
    #### ❌ INCORRECT: Wrong Module Path
    
    \`\`\`python
    from azure.ai.mymodule.models import MyClient # Wrong - Client is not in models
    \`\`\`
    
    ## 2. Authentication Patterns
    
    #### ✅ CORRECT: DefaultAzureCredential + context manager
    
    \`\`\`python
    credential = DefaultAzureCredential()
    with MyClient(endpoint, credential) as client:
    client.do_thing()
    \`\`\`
    
    #### ❌ INCORRECT: Hardcoded Credentials
    
    \`\`\`python
    client = MyClient(endpoint, api_key="hardcoded") # Security risk
    \`\`\`
    
    #### ❌ INCORRECT: Connection string / account key when Entra is supported
    
    \`\`\`python
    client = MyClient.from_connection_string(os.environ["CONNECTION_STRING"]) # Bypasses Entra audit/rotation
    \`\`\`
    
    #### ❌ INCORRECT: Bare client without context manager
    
    \`\`\`python
    client = MyClient(endpoint, credential) # Leaks HTTP transport on exception / interpreter exit
    client.do_thing()
    \`\`\`
    ```
    
    **Critical patterns to document:**
    
    - Import paths (these vary significantly between Azure SDKs)
    - Authentication patterns
    - Client initialization
    - Async variants (`.aio` modules)
    - Common anti-patterns
    
    #### 6.2 Create Test Scenarios
    
    **Location:** `tests/scenarios/<skill-name>/scenarios.yaml`
    
    ```yaml
    config:
      model: gpt-4
      max_tokens: 2000
      temperature: 0.3
    
    scenarios:
      - name: basic_client_creation
        prompt: |
          Create a basic example using the Azure SDK.
          Include proper authentication and client initialization.
        expected_patterns:
          - "DefaultAzureCredential"
          - "MyClient"
          - "with MyClient" # enforce context manager
        forbidden_patterns:
          - "api_key="
          - "hardcoded"
          - "from_connection_string" # prefer Entra over connection strings
        tags:
          - basic
          - authentication
        mock_response: |
          import os
          from azure.identity import DefaultAzureCredential
          from azure.ai.mymodule import MyClient
    
          credential = DefaultAzureCredential()
          with MyClient(
              endpoint=os.environ["AZURE_ENDPOINT"],
              credential=credential,
          ) as client:
              # ... rest of working example
              pass
    ```
    
    **Scenario design principles:**
    
    - Each scenario tests ONE specific pattern or feature
    - `expected_patterns` — patterns that MUST appear
    - `forbidden_patterns` — common mistakes that must NOT appear
    - `mock_response` — complete, working code that passes all checks
    - `tags` — for filtering (`basic`, `async`, `streaming`, `tools`)
    
    #### 6.3 Run Tests
    
    ```bash
    cd tests
    pnpm install
    
    # Check skill is discovered
    pnpm harness --list
    
    # Run in mock mode (fast, deterministic)
    pnpm harness <skill-name> --mock --verbose
    
    # Run with Ralph Loop (iterative improvement)
    pnpm harness <skill-name> --ralph --mock --max-iterations 5 --threshold 85
    ```
    
    **Success criteria:**
    
    - All scenarios pass (100% pass rate)
    - No false positives (mock responses always pass)
    - Patterns catch real mistakes
    
    ### Step 7: Update Documentation
    
    After creating the skill:
    
    1. **Update README.md** — Add the skill to the appropriate language section in the Skill Catalog
       - Update total skill count (line ~73: `> N skills in...`)
       - Update Skill Explorer link count (line ~15: `Browse all N skills`)
       - Update language count table (lines ~77-83)
       - Update language section count (e.g., `> N skills • suffix: -py`)
       - Update category count (e.g., `<summary><strong>Foundry & AI</strong> (N skills)</summary>`)
       - Add skill row in alphabetical order within its category
       - Update test coverage summary (line ~622: `**N skills with N test scenarios**`)
       - Update test coverage table — update skill count, scenario count, and top skills for the language
    
    2. **Regenerate GitHub Pages data** — Run the extraction script and rebuild the docs site from one scoped directory change
    
       ```bash
       (cd docs-site && npx tsx scripts/extract-skills.ts && npm run build)
       ```
    
       This updates `docs-site/src/data/skills.json` which feeds the Astro-based docs site, then rebuilds the site into `docs/`, which is served by GitHub Pages.
    
    3. **Verify AGENTS.md** — Ensure the skill count is accurate
    
    ---
    
    ### Step 8: Regenerate Existing Skills from Latest SDK Sources
    
    Use this workflow when an existing skill has stale examples, outdated API signatures,
    or changed package guidance.
    
    1. **Identify canonical source files first**
    
    For Azure SDK language skills, use official upstream source docs and examples as the source of truth:
    
    - Go: `https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/<service>/<module>/README.md`
    - Go examples: `https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/<service>/<module>/`
    - Rust: `https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/<service>/<crate>/README.md`
    - Rust examples: `https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/<service>/<crate>/examples/`
    - .NET/Java/Python/TS/Go: use current Microsoft Learn package docs + official SDK repos
    
    2. **Refresh skill content surgically**
    
    - Update code snippets to match current constructor/method signatures
    - Keep crate/package names aligned with official publisher guidance
    - Preserve skill structure/frontmatter unless intentionally changing behavior
    - Update "Best Practices" and "Reference Links" when upstream recommendations change
    - For Rust, if code uses `azure_core` types/imports directly, ensure `azure_core` is present in `Cargo.toml`; if only service-crate re-exports are used, direct `azure_core` dependency is optional
    
    ### API Surface Parity Gate (required for every regenerated skill)
    
    Use the language-specific authoritative source as the contract for every snippet in the regenerated skill:
    
    - **Python, .NET, Java, TypeScript, Go**: Treat the current Microsoft Learn API reference as the contract.
    - **Rust**: Treat the official SDK repository (`https://github.com/Azure/azure-sdk-for-rust`) and crates.io documentation as the contract; Rust packages do not have Learn API-reference pages.
    
    Before finalizing any regenerated skill:
    
    1. Identify each SDK type/method shown in snippets (clients, operation groups, model constructors, enum members, long-running methods like `begin_*`).
    2. Verify each symbol and signature against the authoritative source for that language/package (see above).
    3. If the authoritative source shows a different shape (for example nested `properties=...` models, renamed methods, `begin_*` LRO methods), update the snippet to match.
    4. Re-check imports so model/client modules match the authoritative source exactly.
    5. Do not keep compatibility shortcuts that contradict authoritative examples in primary snippets.
    
    ### Scenario Coverage Gate (required for every regenerated skill, all languages)
    
    Regeneration is not complete when snippets compile — it is complete when the skill demonstrates real usage breadth.
    
    Before finalizing any regenerated skill:
    
    1. Identify **hero scenarios** from the current authoritative docs/samples for that SDK (Microsoft Learn where available; otherwise the upstream SDK repo and package documentation).
    2. Ensure each hero scenario is represented in the skill with copy-pastable snippets (or an explicit link to a bundled reference file when too large).
    3. Add/refresh test scenarios so hero flows are validated by harness patterns.
    4. Add at least **one important non-hero scenario** (for example: update/patch, delete/cleanup, export/import, advanced auth mode, paging/filtering, retries/error handling, or LRO monitoring) when supported by the SDK. For Python SDKs that support both sync and async clients, present both forms with equal priority; do not treat either as universally preferred.
    5. For Azure SDK skills, structure `references/` as:
       - `references/capabilities.md` as a concise index that records each hero scenario and where it is covered (`SKILL.md` or a bundled reference), plus links to deeper non-hero references, with no historical/migration narration.
       - `references/non-hero-scenarios.md` for concrete non-hero examples that are intentionally kept out of the main `SKILL.md`.
       - Additional `references/*.md` files for specialized deep-dives (operation groups, tools, evaluator matrices, etc.).
    6. If the SDK has broad operation-group coverage (common in management SDKs), include an operation-group table and explicitly call out which groups are covered in snippets vs. referenced only.
    7. Never claim "full API surface" unless the skill genuinely demonstrates all major operation groups; otherwise state that the skill is optimized for hero workflows plus selected secondary scenarios.
    
    ### Regeneration Workflow Step 3: Validate Regenerated Skill Behavior
    
    ```bash
    (cd tests && pnpm harness <skill-name> --mock --verbose)
    ```
    
    If the skill has a Vally scenario, run that eval as well (locally or in CI) before finalizing.
    
    **Rust regeneration gate (required for Rust skills):**
    
    When regenerating any Rust skill, verify the generated `## Best Practices` section contains these exact first two rules:
    
    1. `Use cargo add to manage dependencies, never edit Cargo.toml directly`
    2. `Add azure_core only when importing azure_core types directly`
    
    Use a content check before finalizing:
    
    ```bash
    rg -n "Use `cargo add` to manage dependencies, never edit `Cargo.toml` directly|Add `azure_core` only when importing `azure_core` types directly" .github/plugins/azure-sdk-rust/skills/**/SKILL.md
    ```
    
    The regeneration is not complete unless both lines are present in each affected Rust skill.
    
    ### Regeneration Workflow Step 4: Regenerate Docs Artifacts After Refresh
    
    ```bash
    (cd docs-site && npx tsx scripts/extract-skills.ts && npm run build)
    ```
    
    ### Regeneration Workflow Step 5: Record What Changed
    
    In the PR/commit notes, include:
    
    - Which upstream docs/examples were used
    - Which snippets/signatures were corrected
    - Which tests/evals were run and their outcomes
    
    #### Python plugin batch recipe: `azure-sdk-python`
    
    Use this when the request is "regenerate all Python skills under azure-sdk-python."
    
    1. **Scope the exact targets first**
    
    ```bash
    # Canonical source of truth for Python plugin skills
    ls .github/plugins/azure-sdk-python/skills/*/SKILL.md
    ```
    
    - Treat `.github/plugins/azure-sdk-python/skills/` as canonical.
    - Keep `.github/skills/<name>` links in sync after edits (symlink check/fix step below).
    
    2. **For each skill, refresh from authoritative sources**
    
    - Always use `microsoft-docs` MCP first for current Microsoft Learn API guidance.
    - Verify the installed package version with `pip show <package>`, then inspect the installed package or official API reference to verify every symbol and signature used in snippets.
    - For Azure SDK skills, prefer package overview + official SDK repo examples.
    - For non-Azure Python skills in this plugin (for example `fastapi-router-py`, `pydantic-models-py`), keep language-specific best-practice variants and skip Azure-specific auth callouts when lifecycle/auth is not applicable.
    
    3. **Apply Python enforcement rules consistently**
    
    - Keep the standard section order for Azure SDK Python skills.
    - Ensure `## Authentication & Lifecycle` starts with the required callout block (verbatim) when applicable.
    - Ensure every client example uses `with` / `async with` lifecycle patterns.
    - Ensure `## Best

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related