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.
npxskills add microsoft/skills--skill skill-creatorLoading…
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.
npxskills add microsoft/skills--skill skill-creatorLoading…
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.
Skills are modular knowledge packages that transform general-purpose agents into specialized experts:
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.
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
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 |
Skills load in three levels:
Keep SKILL.md under 500 lines. Split into reference files when approaching this limit.
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.
name and description (description triggers the skill)| 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 |
When creating skills for Azure SDKs, follow these patterns consistently.
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:
/references/ subdirectories<!-- Token Count: ~XXXX (target: 1100, max: 1500) --> immediately below the skill's H1Decide 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:
/references/batch-operations.md/references/error-handling.md/references/performance.md/references/workflows-comparison.md/references/streaming.md/references/auth-strategies.md/references/tools.md/references/migration.mdDecision: Keep common case in SKILL.md, move edge cases to /references/.
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:
/references/:
/references/batch-operations.md/references/error-handling.md/references/performance.md/references/workflows-comparison.mdExample: 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:
/references/workflows-comparison.md for trade-offs, secondary variations, and deeper context that would otherwise bloat the main fileExample: 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/.
Follow this structure (based on existing Azure SDK skills):
# SDK Namepip install, npm install, etc.DefaultAzureCredential in production, include AZURE_TOKEN_CREDENTIALS (set to prod or <specific_credential>)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)./references/*.md (for Azure SDK skills, include capabilities.md + non-hero-scenarios.md)Scope: Python skills (
-pysuffix) 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:
## Authentication & Lifecycle heading, before the first code sample.azure-ai-voicelive), keep both rules but show only the async form in the bullets.pydantic-models-py).Code sample enforcement. Every client construction in the skill body must demonstrate both rules:
with / async with on every client instantiation in usage examples (not just the auth section).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.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.DefaultAzureCredential from azure.identity.aio in async with credential: alongside the client.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.
These patterns cause bloat and inefficiency. Every skill author must review this section before writing.
ItemPaged for sync pagination" (primary example); link alternatives to /references//references/client = CosmosClient(endpoint, credential). Link to official docs: microsoft-docs MCP.with CosmosClient(endpoint, credential) as client: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:
3. Example count audit:
4. Frontmatter validation:
name matches .github/skills/<name>/SKILL.mddescription includes trigger keywordsdescription is concise (~200 chars is a good target; schema max is 1,024 chars)benchmark_tokens_* and benchmark_quality_* metadata fields are flat strings under metadata4b. Authentication guidance validation (critical for all credentials):
DefaultAzureCredential (supports multiple dev credential types)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 directlyDeveloperToolsCredential for local dev; a specific production credential such as ManagedIdentityCredential for production)/references/auth-strategies.md or official docs for production credential selection4c. 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 errorsvally eval passes (no error-severity findings) when COPILOT_TOKEN is available; otherwise lint-only is acceptable, matching the Vally Evaluation workflow behaviorvally/ spec skip this step — it is optional per skill, not required for every skill5. Spot check:
Output: After validation, annotate the skill header with measured token count:
# Azure Service SDK
<!-- Token Count: ~1180 (target: 1100, max: 1500) -->
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 |
See references/azure-sdk-patterns.md for detailed patterns including:
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.Response<T>, Pageable<T>, Operation<T>, mocking supportPagedIterable/PagedFlux, Reactor typesPagedAsyncIterableIterator, AbortSignal, browser considerationscontext.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.ResponseErrorcargo add, dependency rule for azure_core, Response<T>, Pager<T>, RequestContent::from(), .into_model(), explicit credential types, RBAC roles for Entra ID authenticationThese 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:
### Sync subsection and an ### Async subsection — giving both equal prominence. When the SDK is sync-only or async-only, show only the available mode.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).azure.identity.aio appear in an example, wrap them in async with credential: alongside the client.These rules MUST be explicitly written into every Rust skill's ## Best Practices section as the first items:
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.
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.
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.
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.
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).
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.
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:
microsoft-docs MCP instead of duplicating/references/references/capabilities.md and references/non-hero-scenarios.mdBefore writing your skill: Apply the checklist above directly, then mirror only the structure patterns that fit your use case.
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:
references/migration.md)Examples:
azure-ai-formrecognizer-java → azure-ai-documentintelligence (rebranded service)azure-communication-callingserver-java → azure-communication-callautomation (deprecated, with migration guide)---
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 |
.github/skills/<skill-name>/skills/<language>/<category>/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
Gather concrete examples:
| 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 |
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:
data, Event Hubs → messaging)foundry)Location: .github/skills/<skill-name>/SKILL.md
Naming convention:
azure-<service>-<subservice>-<language>azure-ai-agents-py, azure-cosmos-java, azure-storage-blob-ts, azure-storage-blob-goazblob).github.com/Azure/azure-sdk-for-go/sdk/storage/azblob).For Azure SDK skills:
microsoft-docs MCP for current API patternsWrite bundled resources first, then SKILL.md.
Quality assurance before finalizing:
/references/ if section exceeds max tokensvally lint/vally eval if the skill has a spec (see Efficiency Validation)benchmark_tokens_* and benchmark_quality_* fields under the frontmatter's metadata mapping (flat string values)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 countbenchmark_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)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:
agents, cosmos, blob)azure- prefix and language suffixVerify the symlink:
ls -la skills/python/foundry/agents
# Should show: agents -> ../../../.github/skills/azure-ai-agents-py
Every skill MUST have acceptance criteria and test scenarios.
Location: tests/scenarios/<skill-name>/acceptance-criteria.md
Keep acceptance criteria in the
tests/tree (never besideSKILL.mdinside the skill folder).
Source materials (in priority order):
microsoft-docs MCP)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:
.aio modules)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:
expected_patterns — patterns that MUST appearforbidden_patterns — common mistakes that must NOT appearmock_response — complete, working code that passes all checkstags — for filtering (basic, async, streaming, tools)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:
After creating the skill:
Update README.md — Add the skill to the appropriate language section in the Skill Catalog
> N skills in...)Browse all N skills)> N skills • suffix: -py)<summary><strong>Foundry & AI</strong> (N skills)</summary>)**N skills with N test scenarios**)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.
Verify AGENTS.md — Ensure the skill count is accurate
Use this workflow when an existing skill has stale examples, outdated API signatures, or changed package guidance.
For Azure SDK language skills, use official upstream source docs and examples as the source of truth:
https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/<service>/<module>/README.mdhttps://github.com/Azure/azure-sdk-for-go/tree/main/sdk/<service>/<module>/https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/<service>/<crate>/README.mdhttps://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/<service>/<crate>/examples/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 optionalUse the language-specific authoritative source as the contract for every snippet in the regenerated skill:
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:
begin_*).properties=... models, renamed methods, begin_* LRO methods), update the snippet to match.Regeneration is not complete when snippets compile — it is complete when the skill demonstrates real usage breadth.
Before finalizing any regenerated skill:
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.references/*.md files for specialized deep-dives (operation groups, tools, evaluator matrices, etc.).(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:
Use cargo add to manage dependencies, never edit Cargo.toml directlyAdd azure_core only when importing azure_core types directlyUse 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.
(cd docs-site && npx tsx scripts/extract-skills.ts && npm run build)
In the PR/commit notes, include:
azure-sdk-pythonUse this when the request is "regenerate all Python skills under azure-sdk-python."
# Canonical source of truth for Python plugin skills
ls .github/plugins/azure-sdk-python/skills/*/SKILL.md
.github/plugins/azure-sdk-python/skills/ as canonical..github/skills/<name> links in sync after edits (symlink check/fix step below).microsoft-docs MCP first for current Microsoft Learn API guidance.pip show <package>, then inspect the installed package or official API reference to verify every symbol and signature used in snippets.fastapi-router-py, pydantic-models-py), keep language-specific best-practice variants and skip Azure-specific auth callouts when lifecycle/auth is not applicable.## Authentication & Lifecycle starts with the required callout block (verbatim) when applicable.with / async with lifecycle patterns.## Best Practices starts with the two required user-facing rules (or the documented variant for async-only/provider-pattern skills).references/capabilities.md (index) and references/non-hero-scenarios.md (concrete non-hero examples).# Fast frontmatter/structure validation for every Python skill
python .github/skills/skill-creator/scripts/quick_validate.py .github/plugins/azure-sdk-python/skills/<skill-name>
# Run Python skill harness in mock mode (all *-py scenarios)
(cd tests && pwsh ./run-harness-by-language.ps1 -Language py -Mock)
# Ensure .github/skills links point at plugin canonical skills
python .github/scripts/sync_skill_links.py --plugin azure-sdk-python --check
python .github/scripts/sync_skill_links.py --plugin azure-sdk-python --apply
# Refresh docs site data after content changes
(cd docs-site && npx tsx scripts/extract-skills.ts && npm run build)
.github/plugins/azure-sdk-python/skills/*/SKILL.md is updated or explicitly confirmed current.-py skills passes without regressions.azure-sdk-python.# SDK Name
## Quick Start
[Minimal example]
## Advanced Features
- **Streaming**: See [references/streaming.md](references/streaming.md)
- **Tools**: See [references/tools.md](references/tools.md)
azure-service-skill/
├── SKILL.md (overview + language selection)
└── references/
├── python.md
├── dotnet.md
├── go.md
├── java.md
└── typescript.md
azure-ai-agents/
├── SKILL.md (core workflow)
└── references/
├── tools.md
├── streaming.md
├── async-patterns.md
└── error-handling.md
| Reference | Contents |
|---|---|
references/workflows.md | Sequential and conditional workflows |
references/output-patterns.md | Templates and examples |
references/azure-sdk-patterns.md | Language-specific Azure SDK patterns |
| Don't | Why |
|---|---|
| Create skill without SDK context | Users must provide package name/docs URL |
| Put "when to use" in body | Body loads AFTER triggering |
| Hardcode credentials | Security risk |
| Skip authentication section | Agents will improvise poorly |
| Use outdated SDK patterns | APIs change; search docs first |
| Include README.md | Agents don't need meta-docs |
| Deeply nest references | Keep one level deep |
| Skip acceptance criteria | Skills without tests can't be validated |
| Skip symlink categorization | Skills won't be discoverable by category |
| Use wrong import paths | Azure SDKs have specific module structures |
| Omit sync/async + context-manager bullets from Best Practices in Python skills | End users won't follow rules that aren't written down; examples alone aren't enough |
| Mix sync and async in the same Python example | Demonstrates the anti-pattern the skill is supposed to prevent |
| Ship regenerated skills with zero test scenarios | Hero workflows and regressions cannot be validated |
| Claim full API coverage from a single happy-path sample | Hides operation-group and non-hero gaps users need for production |
Omit references/*.md coverage for non-hero capabilities | Forces advanced capabilities out of context and leaves API breadth undocumented |
Before completing a skill:
Prerequisites:
microsoft-docs MCPSkill Creation:
DefaultAzureCredential for Python/.NET/Java/TS/Go local dev; DeveloperToolsCredential local dev + ManagedIdentityCredential production for Rust)capabilities.md index + dedicated deep-dive files)references/capabilities.md indexes hero/non-hero coverage and links to dedicated non-hero docsreferences/non-hero-scenarios.md contains concrete non-hero examples distinct from hero snippets## Best Practices starts with cargo dependency rule + azure_core direct-import ruleCategorization:
.github/skills/<skill-name>/skills/<language>/<category>/<short-name>../../../.github/skills/<skill-name>Testing:
tests/scenarios/<skill-name>/acceptance-criteria.md created with correct/incorrect patternstests/scenarios/<skill-name>/scenarios.yaml createdpnpm harness <skill> --mock)Documentation:
microsoft-docs MCP for current APIsCreate or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Set up and use 1Password CLI (op). Use when installing the CLI, enabling desktop app integration, signing in (single or multi-account), or reading/injecting/running secrets via op.
CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Set up and use 1Password CLI (op). Use when installing the CLI, enabling desktop app integration, signing in (single or multi-account), or reading/injecting/running secrets via op.
CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).