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.
66
51%
Does it follow best practices?
Impact
94%
1.74xAverage score across 3 eval scenarios
Passed
No known issues
Optimize this skill with Tessl
npx tessl skill review --optimize ./.github/skills/skill-creator/SKILL.mdGuide 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?"
Default assumption: Agents are already capable. Only add what they don't already know.
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 versionMatch specificity to task fragility:
| 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.
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)name and description. The description is the trigger mechanism.| Type | Purpose | When to Include |
|---|---|---|
scripts/ | Deterministic operations | Same code rewritten repeatedly |
references/ | Detailed patterns | API docs, schemas, detailed guides |
assets/ | Output resources | Templates, images, boilerplate |
Don't include: README.md, CHANGELOG.md, installation guides.
When creating skills for Azure SDKs, follow these patterns consistently.
Follow this structure (based on existing Azure SDK skills):
# SDK Namepip install, npm install, etc.DefaultAzureCredentialin production,include AZURE_TOKEN_CREDENTIALS (set to prod or <specific_credential>)ManagedIdentityCredential or WorkloadIdentityCredential for production. DefaultAzureCredential is only recommended for local development. To use DefaultAzureCredential in production, set the environment variable AZURE_TOKEN_CREDENTIALS to prod or the specific target credential./references/*.mdFor 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
from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
# Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
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()
client = ServiceClient(endpoint, credential)// C#
var credential = new DefaultAzureCredential();
var client = new ServiceClient(new Uri(endpoint), credential);// Java
TokenCredential credential = new DefaultAzureCredentialBuilder().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);// 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.
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 docstringsResponse<T>, Pageable<T>, Operation<T>, mocking supportPagedIterable/PagedFlux, Reactor typesPagedAsyncIterableIterator, AbortSignal, browser considerationsResponse<T>, Pager<T>, RequestContent::from(), .into_model(), explicit credential types, RBAC roles for Entra ID authentication.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. **Pick sync OR async and stay consistent.** Do not mix `azure.xxx` sync clients with `azure.xxx.aio` async clients in the same call path. Choose one mode per module.
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. Use a specific token credential (e.g. `ManagedIdentityCredential`, `WorkloadIdentityCredential`) for code that runs in Azure.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 |
| Async-first framework (agent framework, m365-agents) | "This SDK is async-first — use async def handlers and async with throughout." | 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:
### Async variant (or ### Sync variant) subsection with its own complete example.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.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).
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
\`\`\`python
from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
from azure.ai.example import ExampleClient
# Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
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()
client = ExampleClient(
endpoint=os.environ["AZURE_EXAMPLE_ENDPOINT"],
credential=credential
)
\`\`\`
## Core Workflow
\`\`\`python
# 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/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 | 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 | 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)Search official docs first:
# Use microsoft-docs MCP to get current API patterns
# Query: "[SDK name] [operation] [language]"
# Verify: Parameters match the latest SDK versionGather 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-tsFor Azure SDK skills:
microsoft-docs MCP for current API patternsWrite bundled resources first, then SKILL.md.
Frontmatter:
---
name: skill-name-py
description: |
Azure Service SDK for Python. Use for [specific features].
Triggers: "service name", "create resource", "specific operation".
---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-dbSymlink 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-pyEvery skill MUST have acceptance criteria and test scenarios.
Location: tests/scenarios/<skill-name>/acceptance-criteria.md
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
\`\`\`python
credential = DefaultAzureCredential()
client = MyClient(endpoint, credential)
\`\`\`
#### ❌ INCORRECT: Hardcoded Credentials
\`\`\`python
client = MyClient(endpoint, api_key="hardcoded") # Security risk
\`\`\`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"
forbidden_patterns:
- "api_key="
- "hardcoded"
tags:
- basic
- authentication
mock_response: |
import os
from azure.identity import DefaultAzureCredential
from azure.ai.mymodule import MyClient
credential = DefaultAzureCredential()
client = MyClient(
endpoint=os.environ["AZURE_ENDPOINT"],
credential=credential
)
# ... rest of working exampleScenario 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 85Success 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 to update the docs site
cd docs-site && npx tsx scripts/extract-skills.tsThis updates docs-site/src/data/skills.json which feeds the Astro-based docs site.
Then rebuild the docs site:
cd docs-site && npm run buildThis outputs to docs/ which is served by GitHub Pages.
Verify AGENTS.md — Ensure the skill count is accurate
# 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
├── java.md
└── typescript.mdazure-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 |
Before completing a skill:
Prerequisites:
microsoft-docs MCPSkill Creation:
DefaultAzureCredentialCategorization:
.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 APIs10cfecf
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.