{"id":5324,"date":"2026-11-03T19:43:41","date_gmt":"2026-11-03T19:43:41","guid":{"rendered":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2026\/11\/03\/delivering-skills-in-nuget-packages\/"},"modified":"2026-11-03T19:43:41","modified_gmt":"2026-11-03T19:43:41","slug":"delivering-skills-in-nuget-packages","status":"publish","type":"post","link":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2026\/11\/03\/delivering-skills-in-nuget-packages\/","title":{"rendered":"Delivering Skills in NuGet packages"},"content":{"rendered":"<p>Agent skills were <a href=\"https:\/\/www.anthropic.com\/engineering\/equipping-agents-for-the-real-world-with-agent-skills\">introduced by Anthropic<\/a> in 2025 and have quickly become commonplace for AI-driven development. <a href=\"https:\/\/github.com\/dotnet\/skills\">dotnet\/skills<\/a> and <a href=\"https:\/\/impeccable.style\/\">Impeccable skills<\/a> are good examples. Agent skills are typically distributed via git repos. We\u2019ve been working on skill delivery via NuGet packages and found that the approach can be effective. The common thread is that repos and packages are units of development that can be used as distribution vehicles for skills.<\/p>\n<p>Skills solve two main problems: fill in gaps in model knowledge and can prescribe \u201cour way\u201d of approaching a task. New NuGet packages will always be ahead of model training and can benefit from just-in-time skill delivery.<\/p>\n<p>Here\u2019s a quick demo using the <a href=\"https:\/\/www.nuget.org\/packages\/Markout\">markout<\/a> package, whch contains a set of skills:<\/p>\n<pre><code class=\"language-bash\">$ dotnet-inspect package markout -S Skills\r\npath    size\r\nskills\/markout-built-in-shapes\/SKILL.md 9457\r\nskills\/markout-composite-cells-cards\/SKILL.md   6764\r\nskills\/markout-conditional-composition\/SKILL.md 4978\r\nskills\/markout-output-formats\/SKILL.md  7744\r\nskills\/markout\/SKILL.md 8551<\/code><\/pre>\n<h2>Baseline<\/h2>\n<p>We\u2019ve done a lot of experimentation. We\u2019ve found that agents (as a baseline behavior) are capable of finding content in the NuGet cache to learn about a package. This includes reading <code>README.md<\/code> files and even writing throwaway programs that reflect over assembly metadata. Agents using frontier models are <a href=\"https:\/\/avelarder.blog\/2026\/02\/25\/i-am-a-sad-lobster-now-the-day-an-ai-built-its-own-curl\/\">impressively creative<\/a> and can derive surpising insight, although not necessarily cheaply.<\/p>\n<p>The fundamental question is whether they apply that creativity and capability to reverse-engineering documentation from metadata or working on your actual business problem. We sometimes say \u201cwhy not both?\u201d. It\u2019s tough when you\u2019re usage has to fit within a monthly token budget.<\/p>\n<p>This is the problem we set out to solve.<\/p>\n<h2>SKILL.md<\/h2>\n<p>Skills are markdown files with a YAML header, named <code>SKILL.md<\/code>. <a href=\"https:\/\/agentskills.io\/\">agentskills.io<\/a> is the official spec site for the format. NuGet-delivered skills use the same format.<\/p>\n<p>The following example skill can be used to direct agents to run vulnerability checks on project dependencies.<\/p>\n<pre><code class=\"language-markdown\">---\r\nname: vulnerable-nuget-package-check\r\ndescription: Check a .NET project for vulnerable NuGet packages dependencies.\r\n---\r\n\r\nThe .NET SDK includes a `dotnet package` command, which can list vulnerable direct or indirect package dependencies for a given .NET project.\r\n\r\nRun the following command for a project:\r\n\r\n```bash\r\ndotnet package list --vulnerable --include-transitive<\/code><\/pre>\n<p>Update vulnerable package references to patched versions.<\/p>\n<pre><code>\r\n## Conventional delivery\r\n\r\nSkills are distributed via git repos, in one of two ways.\r\n\r\nThe most common approach is to include skills in a typical \"code\" repo. This approach is a great starting point since everyone working on the repo gets the same experience. Skill composition changes with a PR workflow that the team can review or even revert. The [dotnet\/runtime repo](https:\/\/github.com\/dotnet\/runtime\/tree\/main\/.github\/skills) uses this approach. It is a great experience working on that repo and seeing a variety of skills automatically used by Copilot depending on prompts.\r\n\r\nThe other primary approach is skill [marketplace repos](https:\/\/docs.github.com\/en\/copilot\/how-tos\/copilot-cli\/customize-copilot\/plugins-marketplace), such as [dotnet\/skills](https:\/\/github.com\/dotnet\/skills). These repos advertise their skills via [marketplace.json](https:\/\/github.com\/dotnet\/skills\/blob\/main\/.agents\/plugins\/marketplace.json). Users install the marketplace via `\/plugin marketplace add dotnet\/skills` (or similar). `add` is just a wrapper on `git clone`. That means a skill marketplace repo should be small.\r\n\r\nThe advantage of putting skills directly in your repo is that the skills are always there. A good example is using the [Copilot Web Agent](https:\/\/github.com\/copilot). Locally installed marketplace skills don't exist off of your machine unless you take the extra step of committing them to your repo. Neither is better or worse, just different options.\r\n\r\n## NuGet-package delivery\r\n\r\nNuGet packages present a challenge and opportunity for agents. The challenge is that a new package version with new APIs published five minutes ago isn't part of the model. The opportunity is that updated skills can be co-located with updated binaries. That means that every version of a NuGet package can have perfectly-tailored skills for their use. It's very similar to package-resident `README.md` files, which are intended for a different purpose and consumer.\r\n\r\nThe challenge isn't limited to packages published in the last five minutes. Package registries also have a very long tail. It's quite likely models know nothing substantive about most packages.\r\n\r\n`dotnet restore` already pulls packages to your machine to acquire libraries. That means that package-resident `SKILL.md` files will be on your machine as well.\r\n\r\nYou can see [markout](https:\/\/www.nuget.org\/packages\/Markout) package skills on my machine.\r\n\r\n```bash\r\n$ pwd\r\n\/Users\/rich\/git\/dotnet-inspect\/src\/DotnetInspect.Cli\r\n$ dotnet build\r\n$ cat ..\/..\/artifacts\/obj\/dotnet-inspect\/project.assets.json | grep SKILL.md\r\n        \"skills\/markout-built-in-shapes\/SKILL.md\",\r\n        \"skills\/markout-composite-cells-cards\/SKILL.md\",\r\n        \"skills\/markout-conditional-composition\/SKILL.md\",\r\n        \"skills\/markout-output-formats\/SKILL.md\",\r\n        \"skills\/markout\/SKILL.md\",\r\n$ find ~\/.nuget\/packages\/markout\/0.40.0\/ | grep SKILL.md\r\n\/Users\/rich\/.nuget\/packages\/markout\/0.40.0\/skills\/markout-conditional-composition\/SKILL.md\r\n\/Users\/rich\/.nuget\/packages\/markout\/0.40.0\/skills\/markout\/SKILL.md\r\n\/Users\/rich\/.nuget\/packages\/markout\/0.40.0\/skills\/markout-composite-cells-cards\/SKILL.md\r\n\/Users\/rich\/.nuget\/packages\/markout\/0.40.0\/skills\/markout-built-in-shapes\/SKILL.md\r\n\/Users\/rich\/.nuget\/packages\/markout\/0.40.0\/skills\/markout-output-formats\/SKILL.md\r\n$ head -6 \/Users\/rich\/.nuget\/packages\/markout\/0.40.0\/skills\/markout\/SKILL.md\r\n---\r\nname: markout\r\nversion: 0.40.0\r\ndescription: &gt;-\r\n  Use when generating Markdown or other structured output (plain text, ANSI, pretty tables,\r\n  TSV\/JSONL) from C# objects, or when diagnosing Markout source-generator errors such as<\/code><\/pre>\n<p>That\u2019s a pretty good start and quite workable for agents. Package skills are listed in <code>project.assets.json<\/code> making it easy to determine if there are any skills available in a given package graph. However, we wanted to offer better UX than that.<\/p>\n<p>We\u2019ve been working on a few tools for discovering <code>SKILL.md<\/code> files.<\/p>\n<h3>dotnet-inspect<\/h3>\n<p>The following are example workflows with <a href=\"https:\/\/www.nuget.org\/packages\/dotnet-inspect\"><code>dotnet-inspect<\/code><\/a>:<\/p>\n<p>Requesting skills in a package graph:<\/p>\n<pre><code class=\"language-bash\">$ dotnet-inspect package markout -S Skills\r\npath    size\r\nskills\/markout-built-in-shapes\/SKILL.md 9457\r\nskills\/markout-composite-cells-cards\/SKILL.md   6764\r\nskills\/markout-conditional-composition\/SKILL.md 4978\r\nskills\/markout-output-formats\/SKILL.md  7744\r\nskills\/markout\/SKILL.md 8551\r\n$ dotnet-inspect package markout -S Skills --row 4 --print -12\r\n---\r\nname: markout-output-formats\r\nversion: 0.40.1\r\ndescription: &gt;-\r\n  Use when you need output other than default Markdown \u2014 plain text \/ Unicode, ANSI terminal\r\n  (Spectre), pretty aligned tables, or TSV\/JSONL exports \u2014 or when one model must serve several\r\n  formats from a single render path (a CLI `--format` switch). Also covers semantic inline code\r\n  that renders as Markdown code spans but decodes to plain text in TSV\/JSONL. Pick the format with\r\n  a formatter + MarkoutWriterOptions; never hand-build TSV\/JSONL.\r\n  Don't decompile the assembly or web-search the API \u2014 the multi-format idioms are all here.\r\n---<\/code><\/pre>\n<p>It can also accept a project file as input:<\/p>\n<pre><code class=\"language-bash\">$ dotnet new console\r\n$ dotnet package add Mockly\r\n$ ls *.csproj\r\nscratch.csproj\r\n$ dotnet-inspect project scratch.csproj -S Skills\r\n## Skills\r\n\r\nValid Agent Skills documents from direct package dependencies.\r\n\r\n| Package | Version | Path | Size | Name | Description |\r\n| ------- | ------- | ---- | ---- | ---- | ----------- |\r\n| Mockly | 1.13.0 | skills\/mockly\/SKILL.md | 7409 | mockly | Helps write tests using Mockly \u2014 a fluent HTTP mocking library for .NET that intercepts HttpClient calls. Use this skill when writing unit or integration tests that need to mock HTTP requests, configure responses (status codes, JSON, OData, raw content), match headers, capture and inspect requests, limit mock invocations, or assert HTTP interactions with FluentAssertions. |<\/code><\/pre>\n<p>The intended UX with <code>dotnet-inspect<\/code> is that an agent can determine the set of skills available via a project file or directly from the registry. The agent can print those directly to its context or to a file. The file can then be searched or even stored in the repo.<\/p>\n<h3>dotnet-package-skills<\/h3>\n<p><a href=\"https:\/\/www.nuget.org\/packages\/dotnet-package-skills\">dotnet-package-skills<\/a> is another tool that is focused on storing skills in a repo.<\/p>\n<pre><code class=\"language-bash\">$ dotnet-package-skills install\r\nSource:      \/Users\/rich\/git\/dotnet-inspect\/dotnet-inspect.slnx\r\nNuGet global-packages directory: \/Users\/rich\/.nuget\/packages\/\r\nDestination: \/Users\/rich\/git\/dotnet-inspect\/.agents\/skills\r\nScanned 23 packages (direct).\r\n\r\nCopied 5 skills:\r\n  markout (Markout 0.40.1)\r\n  markout-built-in-shapes (Markout 0.40.1)\r\n  markout-composite-cells-cards (Markout 0.40.1)\r\n  markout-conditional-composition (Markout 0.40.1)\r\n  markout-output-formats (Markout 0.40.1)\r\n\r\nIgnored 22 packages without valid bundled skills\r\n$ git status\r\nOn branch main\r\nYour branch is up to date with 'origin\/main'.\r\n\r\nUntracked files:\r\n  (use \"git add &lt;file&gt;...\" to include in what will be committed)\r\n        .agents\/\r\n\r\nnothing added to commit but untracked files present (use \"git add\" to track)\r\n$ git add .\r\n$ git status\r\nOn branch main\r\nYour branch is up to date with 'origin\/main'.\r\n\r\nChanges to be committed:\r\n  (use \"git restore --staged &lt;file&gt;...\" to unstage)\r\n        new file:   .agents\/skills\/.dotnet-package-skills.json\r\n        new file:   .agents\/skills\/markout-built-in-shapes\/SKILL.md\r\n        new file:   .agents\/skills\/markout-composite-cells-cards\/SKILL.md\r\n        new file:   .agents\/skills\/markout-conditional-composition\/SKILL.md\r\n        new file:   .agents\/skills\/markout-output-formats\/SKILL.md\r\n        new file:   .agents\/skills\/markout\/SKILL.md<\/code><\/pre>\n<p>This is an easy way to add skills into your repo and to ensure that they are always available. It is up to you to ensure that the skills stay up to date as matching <code>PackageRef<\/code> entries are udpated. It might be useful to write a skill to do both at the same time.<\/p>\n<h3>NuGet MCP<\/h3>\n<p><a href=\"https:\/\/learn.microsoft.com\/nuget\/concepts\/nuget-mcp-server\">NuGet MCP<\/a> is a useful tool for giving agents a deep and broad undertanding of NuGet, both for your local project and of your registry. It hasn\u2019t yet been updated for skills. That\u2019s a project we intend to take on soon.<\/p>\n<h2>Learnings<\/h2>\n<p>Package-delivered skills are not a special kind of skill. As already stated, skills can already be delivered in multiple ways. Packages are a variation on a theme using the same format. That means that conventional skill eval applies.<\/p>\n<p>Agent skills can be boiled down to delivering two benefits: efficacy (ability to deliver right answers) and efficiency (deliver answers cheaply). That doesn\u2019t mean that agent skills <em>always<\/em> deliver efficacy and efficiency benefits. They <em>can<\/em> deliver those benefits. They can also deliver the opposite if they are badly written or tested.<\/p>\n<p>The challenge with models is that cost is a major factor. If I include a <code>SKILL.md<\/code> in my package and your agent costs increase, that\u2019s bad. That means that maintainers need to perform skill eval. Maintainers should improve or remove skills that their users report as ineffective or costly.<\/p>\n<p>With frontier models, we didn\u2019t find much room to improve efficacy, due to creative capability. With weaker models, we observed significant efficacy underperformance and variability due to lower skill compliance.<\/p>\n<p>We used <a href=\"https:\/\/en.wikipedia.org\/wiki\/Pareto_efficiency\">Pareto efficiency<\/a> as a corrective tool for our efforts. Basic idea: \u201cDo no harm\u201d. Our early thinking was using skills to bring \u201cmini\u201d-level models up to frontier. That\u2019s a nice idea, but not generally practical in our experience. The challenge is that one set of skills is delivered to all models. Improving efficiency for Anthropic Haiku by 50% but reducing it for Opus by 10% is a bad trade. You\u2019ve made agent work more expensive for your Opus users and Opus tokens cost a lot more. Your Opus users would be right to complain.<\/p>\n<p>Our primary focus has been testing with frontier models as a result. Testing only with cheap models (as attractive as that might be) is considered (by our findings) an anti-pattern and is not advised.<\/p>\n<h2>Next Steps<\/h2>\n<p>We\u2019re working on guidance for maintainers. Maintainers already familiar with skill eval will be a step ahead. Skills delivered via NuGet packages don\u2019t change much. Our focus is figuring out how to deliver high-quality skills on a budget. This includes determining if skills deliver value.<\/p>\n<p>Maintainers have been delivering markdown with packages for a long time. It\u2019s always been an inert asset. Agents change that. We need to update safety guidance for consumers. The same guidance applies as before: \u201conly use packages from maintainers you trust\u201d. Agent consumption of markdown adds a new <a href=\"https:\/\/the-agent-report.com\/2026\/05\/protestware-coding-agents-jqwik-supply-chain\/\">threat vector<\/a> that needs to be considered.<\/p>\n<p>Skill-delivery is an important new option for NuGet packages. We believe it offers the opportunity to make packages self-documenting and efficient to integrate into an app.<\/p>\n<p>The post <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/delivering-skills-in-nuget-packages\/\">Delivering Skills in NuGet packages<\/a> appeared first on <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\">.NET Blog<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Agent skills were introduced by Anthropic in 2025 and have quickly become commonplace for AI-driven development. dotnet\/skills and Impeccable skills [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":94,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[7],"tags":[],"class_list":["post-5324","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet"],"_links":{"self":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/5324","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/comments?post=5324"}],"version-history":[{"count":0,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/5324\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/media\/94"}],"wp:attachment":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/media?parent=5324"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/categories?post=5324"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/tags?post=5324"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}