MCPInstall

opentelemetry-net-instrumentation

Provides guidance for implementing OpenTelemetry instrumentation in .NET codebases, covering tracing (Activities/Spans), metrics, logs, naming conventions, error handling, performance, SDK setup, resources, context propagation, and API design best practices.

Installs
414
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/aaronontheweb/dotnet-skills --skill opentelemetry-net-instrumentation
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads opentelemetry-net-instrumentation automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

OpenTelemetry .NET Instrumentation Skill

When to Use

  • Adding OpenTelemetry instrumentation to .NET code (traces, metrics, logs)
  • Creating or modifying ActivitySources, Meters, or ILogger usage
  • Setting up the OpenTelemetry SDK, resources, exporters, or sampling
  • Reviewing telemetry implementations for spec compliance
  • Optimizing instrumentation performance
  • Designing telemetry APIs that become part of the public surface
  • Implementing context propagation across service boundaries

Architecture: .NET Is Different

CRITICAL: The .NET OpenTelemetry implementation is fundamentally different from other platforms. .NET provides tracing, metrics, and logging APIs in the framework itself. That means OTel does not provide a separate instrumentation API — it uses the built-in .NET APIs and acts as the collection/export layer.

The Three Built-in .NET APIs (Primary — Zero Dependencies)

Signal.NET Framework APINamespace
TracingActivitySource / ActivitySystem.Diagnostics
MetricsMeter / Counter<T> / Histogram<T> / etc.System.Diagnostics.Metrics
LoggingILogger<T>Microsoft.Extensions.Logging

These are the primary and only APIs library authors should use for instrumentation. They ship with the .NET runtime — no NuGet packages required.

The OTel Collection/Export Layer (Secondary — Application Root Only)

OTel NuGet packages are the collection and export layer, added only at the application composition root (not in libraries):

PackagePurposeWhen to add
OpenTelemetry.Extensions.HostingDI integration for ASP.NET Core / generic hostApplication only
OpenTelemetry.Exporter.ConsoleConsole exporter (dev/testing)Application only
OpenTelemetry.Exporter.OpenTelemetryProtocolOTLP exporter (production)Application only
OpenTelemetry.Exporter.Prometheus*Prometheus metrics endpointApplication only
OpenTelemetry.Instrumentation.AspNetCoreAuto-instrument ASP.NET Core requestsApplication only
OpenTelemetry.Instrumentation.HttpAuto-instrument HttpClient callsApplication only
OpenTelemetry.Instrumentation.SqlClientAuto-instrument SQL callsApplication only

Package Decision Guide

Before adding ANY OpenTelemetry NuGet package, discuss the trade-off with the user:

"You're about to add an OTel NuGet package. Is this an application where you need to export telemetry to an observability backend (Jaeger, Prometheus, OTLP collector)? If you're writing a library, you likely need zero OTel packages — just use System.Diagnostics.ActivitySource / System.Diagnostics.Metrics.Meter and let the consuming application configure the export pipeline. Do you want to proceed?"

Library authors: Add nothing. Use only System.Diagnostics.* and ILogger. The consuming application wires up the SDK and exporters.

Application authors: Add OpenTelemetry.Extensions.Hosting + the exporters and instrumentation libraries you need. See sdk-resources-and-logs-reference.md for full setup patterns.

Never add OpenTelemetry.Api to a library — System.Diagnostics.* IS the API.

For SDK setup, resource configuration, exporters, sampling, and logs integration, see sdk-resources-and-logs-reference.md.

Core Principles

Resiliency First

CRITICAL: Exceptions in diagnostic/tracing/metrics logic MUST NEVER impact application processing.

  • Assume Activity instances can be null. Always protect against null Activity references except in Activity extension methods (use activity?.ExtensionMethod())
  • Guard all instrumentation code with appropriate null checks

API Surface Awareness

  • Any telemetry emitted becomes part of the public API surface
  • Changes are subject to breaking changes guidelines
  • Telemetry should be emitted by default (users opt-in to collection via OpenTelemetry extensions)
  • Exception: High-cardinality metric dimensions may require explicit opt-in

Standards Compliance

Traces / Spans (Activities)

ActivitySource Setup

// ✅ CORRECT: Use ActivitySource, not DiagnosticSource
public class MyFeature
{
    // Primary ActivitySource - name typically matches the component or NuGet package name
    private static readonly ActivitySource ActivitySource = new("MyApp.MyComponent", "1.0.0");

    // Specialized ActivitySource for opt-in scenarios
    private static readonly ActivitySource DetailedActivitySource = new("MyApp.MyComponent.Detailed", "1.0.0");
}

Rules:

  • Every component defines a primary ActivitySource for mainstream activities
  • Name typically matches the component or NuGet package (e.g., "MyCompany.MyLibrary")
  • Version the ActivitySource using SemVer
  • Create separate ActivitySources for specialized or opt-in scenarios. Use hierarchical source names, e.g. MyCompany.MyLibrary and MyCompany.MyLibrary.Detailed, so consuming applications can subscribe only to the sources they want via AddSource(...) and backends can filter by instrumentation scope.

Creating Activities

// ✅ Check HasListeners, null-check, then guard expensive work behind IsAllDataRequested
if (ActivitySource.HasListeners())
{
    using var activity = ActivitySource.StartActivity("ProcessItem", ActivityKind.Internal);
    if (activity != null && activity.IsAllDataRequested)
    {
        activity.DisplayName = "Processing order #12345";
        activity.SetTag("app.item_id", itemId);
        activity.SetTag("app.item_type", itemType);
    }
}

// ❌ WRONG: Don't start activities in fire-and-forget tasks where the
// using scope ends before the async work completes (AsyncLocal context is lost)
async Task HelperAsync()
{
    using var activity = ActivitySource.StartActivity("Helper");
    _ = Task.Run(() => DoWorkAsync()); // ❌ activity disposed before task completes
}

Rules:

  • Check ActivitySource.HasListeners() before creating (zero-allocation fast path)
  • Always null-check Activity after creation (listener may filter or sample it out)
  • Never start activities in async helper methods (Activity.Current uses AsyncLocal)
  • Guard expensive tag computation behind activity.IsAllDataRequested
  • Use W3C TraceContext. .NET Core 3.0+ / .NET 5+ uses it by default; older TFMs or .NET Framework apps may set Activity.DefaultIdFormat = ActivityIdFormat.W3C at startup and use Activity.ForceDefaultIdFormat = true to override hierarchical parents.

Activity Naming

// ✅ Unique operation name, friendly display name (null-check before accessing)
using var activity = ActivitySource.StartActivity(
    name: "ProcessItem",              // Unique, identifies class of spans
    kind: ActivityKind.Internal
);
if (activity != null)
    activity.DisplayName = "Processing order #12345"; // User-friendly, can be specific

// ❌ WRONG: Don't include runtime data in operation name
using var badActivity = ActivitySource.StartActivity($"Process_{itemId}"); // ❌

Rules:

  • Each span type has unique OperationName (identifies statistically interesting class of spans)
  • Operation name should NOT contain runtime data (only compile/config-time info)
  • Use human-readable DisplayName for specifics
  • Follow OpenTelemetry span naming conventions

SpanKind Selection

Choose the correct ActivityKind to clarify the span's role in distributed tracing:

ActivityKindOTel SpanKindWhen to use
InternalINTERNALDefault — in-process operations not crossing a remote boundary
ServerSERVERProcessing an incoming request/response call (HTTP server, gRPC server, RPC server)
ClientCLIENTMaking an outgoing request/response call (HTTP client, database client, RPC call)
ProducerPRODUCEREnqueuing/publishing deferred work (message queue publish, event emit, job enqueue)
ConsumerCONSUMERDequeuing/processing deferred work (message queue receive, event handle, job dequeue)

Rules:

  • A single span SHOULD NOT serve more than one purpose
  • Create the outgoing span before injecting its SpanContext into the request. If you inject first, the parent's context propagates instead and the outgoing span ends up dangling (no connection to the downstream call).
  • See traces-and-propagation-reference.md for detailed SpanKind guidance with examples

Span Attributes (Tags)

// ✅ Application code: use your own namespace
activity?.SetTag("myapp.order_id", orderId);
activity?.SetTag("myapp.payment.status", "confirmed");

// ✅ Manual infrastructure instrumentation: use semantic conventions
// activity?.SetTag("db.system.name", "postgresql"); // custom database client
// activity?.SetTag("http.request.method", "GET"); // custom HTTP transport

// Values can be strings, numbers, booleans, or homogeneous arrays
activity?.SetTag("app.item_count", 42);
activity?.SetTag("app.related_ids", new int[] { 1, 2, 3 });

// ❌ WRONG: PascalCase, hyphen delimiter, plural, or unrelated namespace
activity?.SetTag("MyApp.OrderId", orderId);     // ❌ Wrong case
activity?.SetTag("myapp.order-id", orderId);    // ❌ Wrong delimiter

Rules:

  • Namespace prefix matching your component: myapp.*, myapp.db.*
  • All lowercase, underscore (_) delimiters, singular form
  • Attribute values: string, boolean, double, int64, byte arrays, homogeneous arrays (null/empty valid per AnyValue spec)
  • Business/domain attributes: use your own namespace (myapp.*).
  • HTTP, database, messaging, or RPC concepts you manually instrument: use semantic conventions. Do not duplicate attributes already emitted by auto-instrumentation. Do not use OTel namespaces as prefixes for custom attributes.

Activity Status and Errors

try
{
    await ProcessItemAsync(); // ✅ success: leave status Unset, do not call SetStatus(Ok) — see rules below
}
catch (Exception ex)
{
    if (activity != null)
    {
        activity.SetStatus(ActivityStatusCode.Error, ex.Message); // modern API
        activity.SetTag("error.type", ex.GetType().FullName);
    }
    throw;
}

Rules (per Recording Errors and the Set Status API spec):

  • Leave span status Unset on success — do not call SetStatus(ActivityStatusCode.Ok).
  • Ok is for application code, not instrumentation libraries. The trace API spec: "Instrumentation Libraries SHOULD NOT set the status code to Ok, unless explicitly configured to do so (...) Application developers and Operators may set the status code to Ok" — typically to override a library-reported Error they've decided isn't a real failure (e.g. suppressing a noisy 404). Once set, Ok is final; later calls are ignored."
  • On failure: SHOULD set ActivityStatusCode.Error, SHOULD set the error.type tag, SHOULD set the status description to the exception message.
  • Use SetStatus — legacy otel.status_code/otel.status_description tags are no longer needed.
  • Do not record errors that were retried or handled and let the operation complete gracefully — Error status and error.type describe operations that failed, not ones that recovered.

Recording Exceptions — Keep Emitting Span Events, Add the Logs Opt-In

exceptions-spans — the convention behind Activity.AddEvent(new ActivityEvent("exception", ...)) — carries a Deprecated status in favor of exceptions-logs, but the .NET ecosystem has not followed yet: no OpenTelemetry.* .NET package implements the spec's OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN opt-in (verified against OpenTelemetry.Api 1.17.0), and OpenTelemetry.Instrumentation.AspNetCore 1.17.0 itself still records exceptions via Activity.AddException, i.e. span events. That means the exporters, backends, and dashboards a typical .NET user has wired up today are built to read exception span events, not log-based exceptions. Keep implementing span events as the default — dropping them because the underlying spec document is marked Deprecated will silently break exception visibility for anyone still on today's tooling. Layer the newer logs-based path on top as an opt-in, exactly as the spec's own transition guidance describes for instrumentations moving off span events:

// Mirrors the spec's OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN values: unset/anything else → spans only (today's default), "logs/dup" → both, "logs" → logs only.
private static readonly string? ExceptionSignalOptIn = Environment.GetEnvironmentVariable("OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN");
private static readonly bool EmitSpanEvents = ExceptionSignalOptIn != "logs";
private static readonly bool EmitLogs = ExceptionSignalOptIn is "logs" or "logs/dup";

try
{
    await ProcessItemAsync();
}
catch (Exception ex)
{
    activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
    activity?.SetTag("error.type", ex.GetType().FullName);

    if (EmitSpanEvents) // ✅ default — what current .NET tooling and dashboards actually consume today
    {
        activity?.AddEvent(new ActivityEvent("exception", tags: new ActivityTagsCollection
        {
            ["exception.type"] = ex.GetType().FullName,
            ["exception.message"] = ex.Message,
            ["exception.stacktrace"] = ex.ToString()
        }));
    }

    if (EmitLogs) // opt-in — the spec's forward direction; pass the exception instance while `activity` is still Activity.Current so the SDK derives trace_id/span_id and exception.type/message/stacktrace from it
    {
        logger.LogError(ex, "Item processing failed");
    }

    throw;
}

Rules:

  • Don't set exception.escaped on the span event — it's deprecated outright: "no longer recommended to record exceptions that are handled and do not escape the scope of a span."
  • Support OTEL_SEMCONV_EXCEPTION_SIGNAL_OPT_IN (logs / logs/dup) so consumers who are ready can opt into logs or dual-emission, but default to spans-only — this is the spec's own transition guidance, not an optional nicety, and it exists precisely so nobody has to choose one signal over the other before they're ready.
  • When emitting logs (opt-in or dual), pick severity per exceptions-logs: ERROR for unhandled exceptions (especially on SERVER/CONSUMER spans), WARN for exceptions expected to be handled by the caller (especially on CLIENT/PRODUCER spans), DEBUG for exceptions that don't indicate an actual issue (e.g., a request cancelled client-side), FATAL only when the exception causes application shutdown.
  • The log call MUST happen while the span it's associated with is still current — the spec requires "exception events emitted by instrumentations that also record spans for the same operation MUST be associated with the corresponding span context." Logging from a detached error-reporting callback after the using activity scope has ended silently correlates to the wrong span, or none. See Accessing Activities below.
  • Only move to logs-only once you've held dual-emission for at least six months on a stable major version (the spec's own minimum) and confirmed your actual consumers read log-based exceptions — not on a fixed timeline alone.

See traces-and-propagation-reference for the full pattern, including how a library with no logging dependency in its core can still expose a callback so a separate OTel integration package can capture exception details while the right span is active.

Accessing Activities

var current = Activity.Current; // ❌ may be a user-created ambient span
using var ownedActivity = ActivitySource.StartActivity("MyOperation"); // ✅ captured reference
ownedActivity?.SetTag("myapp.key", value);

Rules: Do not rely on Activity.Current for spans you own; user code can replace it via AsyncLocal. Pass/store captured Activity only while alive. Store ActivityContext for propagation identity.

Span Links

Links connect a span to other spans that are causally related but not in a direct parent-child relationship — batch processing, scatter/gather, trace boundary crossings.

var links = new List<ActivityLink>
{
    new(activityContext1),
    new(activityContext2),
};

var activity = ActivitySource.StartActivity(
    ActivityKind.Internal, name: "batch-process", links: links);

See traces-and-propagation-reference.md for full link patterns including batch processing, scatter/gather, and trace boundary crossing.

Context Propagation

Distributed tracing requires propagating trace context across process boundaries (HTTP calls, message queues, etc.) using W3C traceparent headers. In .NET, this is handled by DistributedContextPropagator. The OTel SDK configures W3C TraceContext propagation by default.

See traces-and-propagation-reference.md for propagation patterns, custom propagators, and manual inject/extract for non-standard transports.

Metrics

Meter and Metrics Class Setup

public sealed class OrderProcessingMetrics : IDisposable
{
    private readonly Meter meter = new("MyApp.OrderProcessing", "1.0.0");
    private readonly Histogram<double> processingDuration =
        meter.CreateHistogram<double>("myapp.order.processing.duration", unit: "s");
    private readonly Counter<long> itemsProcessed =
        meter.CreateCounter<long>("myapp.order.processing.count", unit: "{order}");

    public void Dispose() => meter.Dispose();
}

Naming Conventions (follow OTel semantic conventions):

  • Singular names, nested hierarchy: myapp.order.processing.duration
  • Define units (s, ms, {item}, {connection}); avoid technical suffixes (_counter, _histogram)
  • Start with pre-1.0.0 version until adoption proven

Instrument Type Overview

.NET provides 7 metric instrument types. Choose the right one for your measurement:

Instrument.NET APIBehaviorTypical Use
CounterCreateCounter<T>Monotonically increasingRequest counts, error counts
UpDownCounterCreateUpDownCounter<T>Increases or decreasesQueue size, active connections
HistogramCreateHistogram<T>Distribution of valuesDurations, response sizes
GaugeCreateGauge<T> (.NET 9+)Synchronous instant valueCurrent measurement recording
ObservableCounterCreateObservableCounter<T>Async callback, monotonicPeriodically polled totals
ObservableGaugeCreateObservableGauge<T>Async callback, non-monotonicCPU/memory usage
ObservableUpDownCounterCreateObservableUpDownCounter<T>Async callback, bi-directionalActive tasks by priority

See metrics-and-instruments-reference.md for full creation/recording examples and observable callback patterns.

Metric Recording Method Naming

// ✅ Action/outcome-based naming, separate methods per outcome
public void OrderProcessingSucceeded(string orderType, TimeSpan duration) { /* Record */ }
public void OrderProcessingFailed(string orderType, Exception ex, TimeSpan duration) { /* Record */ }
public void ConnectionOpened() => connectionsOpen.Add(1);
public void ConnectionClosed() => connectionsOpen.Add(-1);

// ❌ WRONG: Name after metric, confusing signature
public void RecordOrderProcessingDuration(...) { } // ❌ don't name after metric
public void RecordError(bool succeeded, Exception? ex) { } // ❌ confusing signature

Rules:

  • Name after action/outcome (OrderProcessingSucceeded), NOT after metric (RecordXxx)
  • Separate methods per outcome (avoid boolean flags + optional exceptions)
  • Event-based naming for state changes: ConnectionOpened(), ItemQueued()

Metric Dimensions

// ✅ Low-cardinality, predefined dimensions
processingDuration.Record(duration.TotalSeconds,
    new KeyValuePair<string, object?>("myapp.order_type", orderType),  // bounded set
    new KeyValuePair<string, object?>("outcome", "success"));         // bounded set

// ❌ High-cardinality: unbounded values cause cardinality explosion
failureCount.Add(1, new KeyValuePair<string, object?>("order_id", orderId)); // ❌ unbounded

Rules:

  • Dimensions MUST be predefined and low-cardinality (item type, queue name, outcome)
  • Avoid unbounded values (each unique value = new time series row → cardinality explosion)
  • High-cardinality dimensions MUST be opt-in configuration
  • Consistent names across components: myapp.region means the same everywhere
  • Users can enable exemplars for trace correlation (not via dimensions)

Performance Requirements

Instrumentation MUST be cheap by default. Follow these rules to minimize overhead:

Zero-Allocation Fast Path

// ✅ CORRECT: Guard with cheap checks
if (ActivitySource.HasListeners())
{
    using var activity = ActivitySource.StartActivity("Operation");
    // ... expensive work
}

// ✅ CORRECT: Use TagList (struct) for metrics
var tags = new TagList
{
    { "myapp.order_type", orderType },
    { "outcome", "success" }
};
counter.Add(1, tags);

Timing

// ✅ Timestamp math (no allocation)
var startTime = Stopwatch.GetTimestamp();
try { await ProcessAsync(); }
finally { var duration = Stopwatch.GetElapsedTime(startTime); metrics.OrderProcessingSucceeded(orderType, duration); }

// ❌ Allocates: Stopwatch.StartNew() or IDisposable timing wrappers

Avoid Hidden Allocations

// ❌ Allocates: string interpolation without IsAllDataRequested guard
activity?.SetTag("item", $"Processing {itemId}"); // ❌

// ✅ Guard expensive work behind IsAllDataRequested
if (activity?.IsAllDataRequested == true)
    activity.SetTag("item", $"Processing {itemId}");

Rules:

  • No Stopwatch.StartNew() (use Stopwatch.GetTimestamp()/GetElapsedTime)
  • Prefer TagList (struct) over arrays/dictionaries
  • No LINQ, string interpolation, or async state machines in hot paths without guards

Testing Requirements

Span Tests

[Test]
public async Task Should_create_processing_span_with_correct_parent()
{
    // Arrange
    using var parent = new Activity("Parent").Start();

    // Act
    await handler.Handle(item);

    // Assert
    var processingSpan = recordedActivities.Single(a => a.OperationName == "ProcessItem");
    Assert.AreEqual(parent.Id, processingSpan.ParentId);
    Assert.AreEqual("myapp.item_type", processingSpan.Tags.First().Key);
}

[Test]
public void Should_not_introduce_breaking_changes_to_span_names()
{
    // Ensures string values in span names are under test
    Assert.AreEqual("ProcessItem", MyFeature.SpanName);
}

Rules:

  • Test which spans activities connect to
  • Test string values (span names, tag names) to prevent breaking changes
  • Remember: telemetry is part of public API

Versioning

  • Telemetry versioning decoupled from package version
  • Use SemVer semantics
  • Traces and Metrics use separate versions (evolve independently)
  • Start with pre-1.0.0 version until adoption/usefulness proven
private static readonly ActivitySource ActivitySource = new("MyApp.MyComponent", "0.9.0");
private readonly Meter meter = new("MyApp.MyComponent", "0.8.0");

Logs

.NET logs integrate with OpenTelemetry through the built-in ILogger API. The OTel SDK provides AddOpenTelemetry() on the logging builder to collect, process, and export logs. Log records are automatically correlated with traces via TraceId/SpanId.

See sdk-resources-and-logs-reference.md for full logs integration patterns including correlation, redaction, structured logging, and severity filtering.

Reference Files

  • traces-and-propagation-reference.md: SpanKind deep dive with examples, Span Links (batch, scatter/gather, trace boundary), Context Propagation (W3C traceparent, DistributedContextPropagator, custom propagators), Baggage, and the full modern exception recording pattern.
  • metrics-and-instruments-reference.md: All 7 metric instrument types with creation/recording code and when-to-use guidance, observable instrument callback patterns, dimensions deep dive, exemplars, aggregation defaults, and units.
  • sdk-resources-and-logs-reference.md: SDK initialization (ASP.NET Core + Console), Resource configuration (ResourceBuilder, AddService, AddDetector, custom detectors), Exporters (OTLP, Console, Jaeger, Zipkin, Prometheus), Instrumentation Libraries, Sampling (built-in, custom, env vars, head/tail-based), Logs integration (ILogger, correlation, redaction, structured logging), and environment variable configuration.

References

FAQ

What does the opentelemetry-net-instrumentation skill do?

Provides guidance for implementing OpenTelemetry instrumentation in .NET codebases, covering tracing (Activities/Spans), metrics, logs, naming conventions, error handling, performance, SDK setup, resources, context propagation, and API design best practices.

How do I install opentelemetry-net-instrumentation?

Run npx skills add https://github.com/aaronontheweb/dotnet-skills --skill opentelemetry-net-instrumentation in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/opentelemetry-net-instrumentation/ (personal) or .claude/skills/opentelemetry-net-instrumentation/ (project).

Which AI agents can use opentelemetry-net-instrumentation?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is opentelemetry-net-instrumentation safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains opentelemetry-net-instrumentation?

It is published by aaronontheweb in aaronontheweb/dotnet-skills. It has 414 recorded installs.

More from aaronontheweb/dotnet-skills

View all →

modern-csharp-coding-standards

aaronontheweb/dotnet-skills

Write modern, high-performance C code using records, pattern matching, value objects, async/await, Span /Memory , and best-practice API design patterns. Emphasizes functional-style programming with C 12+ features.

Backend & APIs2.2K installs

csharp-concurrency-patterns

aaronontheweb/dotnet-skills

Choosing the right concurrency abstraction in .NET - from async/await for I/O to Channels for producer/consumer to Akka.NET for stateful entity management. Avoid locks and manual synchronization unless absolutely necessary.

Backend & APIs1.6K installs

efcore-patterns

aaronontheweb/dotnet-skills

Entity Framework Core best practices including NoTracking by default, query splitting for navigation collections, migration management, dedicated migration services, and common pitfalls to avoid.

dependency-injection-patterns

aaronontheweb/dotnet-skills

Organize DI registrations using IServiceCollection extension methods. Group related services into composable Add methods for clean Program.cs and reusable configuration in tests.

Security676 installs

database-performance

aaronontheweb/dotnet-skills

Database access patterns for performance. Separate read/write models, avoid N+1 queries, use AsNoTracking, apply row limits, and never do application-side joins. Works with EF Core and Dapper.

Data & Databases672 installs

api-design

aaronontheweb/dotnet-skills

Design stable, compatible public APIs using extend-only design principles. Manage API compatibility, wire compatibility, and versioning for NuGet packages and distributed systems.

Backend & APIs667 installs

Popular backend & apis skills

View category →

find-skills

vercel-labs/skills

Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.

OfficialBackend & APIs4.1M installs

entra-app-registration

microsoft/azure-skills

Guides Microsoft Entra ID app registration, OAuth 2.0 authentication, and MSAL integration. USE FOR: create app registration, register Azure AD app, configure OAuth, set up authentication, add API permissions, generate service principal, MSAL example, console app auth, Entra ID setup, Azure AD authentication. DO NOT USE FOR: Key Vault secrets (use azure-keyvault-expiration-audit), general Azure resource security guidance.

OfficialBackend & APIs566.7K installs

This skill should be used when the user wants to "write agent code", "build an agent with ADK", "add a tool", "create a callback", "define an agent", "use state management" — in a project that needs ADK (Agent Development Kit) API patterns and code examples. It provides a quick reference for agent types, tool definitions, orchestration patterns, callbacks, state management, the graph Workflow API, and reference recipes to study. Do NOT use for scaffolding (use google-agents-cli-scaffold) or deployment (use google-agents-cli-deploy).

Backend & APIs514.8K installs

embedded-captions

heygen-com/hyperframes

Add captions or subtitles to an existing single-subject talking-head video without editing the footage. Use for plain verbatim captions, cinematic captions embedded behind the subject, VFX captions, “炸/特效/酷炫字幕,” or a named identity from the 35-style catalog. Route by visual identity, not by backend engine. The quiet anchor rail is the default; embed every word only when the user explicitly wants a fully cinematic treatment. The workflow runs locally end to end, including transcription and subject matting; split multi-shot footage before applying it.

Backend & APIs453.3K installs

entra-agent-id

microsoft/azure-skills

Provision Microsoft Entra Agent Identity Blueprints, BlueprintPrincipals, and per-instance Agent Identities via Microsoft Graph, and configure OAuth 2.0 token exchange (fmipath, OBO, cross-tenant) including the Microsoft Entra SDK for AgentID sidecar. USE FOR: Agent Identity Blueprint, BlueprintPrincipal, agent OAuth, fmipath token exchange, agent OBO, Workload Identity Federation for agents, polyglot agent auth, Microsoft.Identity.Web.AgentIdentities. DO NOT USE FOR: standard Entra app registration (use entra-app-registration), Microsoft Foundry agent authoring (use microsoft-foundry).

OfficialBackend & APIs336.6K installs

neon

neondatabase/agent-skills

Overview of Neon, a complete set of cloud backend primitives around Lakebase Postgres: Auth, Object Storage, Functions, the AI Gateway, and Realtime. Start here to choose Neon for undecided login, files, APIs, and LLM calls, set up the CLI or MCP server, and follow the branch-first workflow. Use when building an app or backend on Neon, or when "Neon" or "Lakebase Postgres" is mentioned. Child skill neon-postgres wins for an existing DATABASEURL, SQL, schema, inspect, or search. Child skill neon-auth wins for login, users, sessions, identity routing, and Managed Better Auth setup. Child skill neon-realtime wins for live queries in reactive apps and agents. Also use for object storage, S3, buckets, serverless functions, function triggers, cron, AI gateway, LLM calls, realtime, logs, Loki, Grafana, observability, postgres, database, backend, Claimable Neon, neon.new, or a no-signup database.

Backend & APIs237.1K installs