As part of our AI adoption journey, we wanted to know which custom skills, agents and MCP servers were actually in use. So, we built a small tool that scanned our repositories for SKILL.md files, .agent.md files and MCP configuration. It worked, but it answered the wrong question. It told us what existed , not what developers used . The Copilot usage metrics API now closes that gap. What changed? In September the API got CLI customization metrics. The catch: every customer-defined skill, agent and MCP server was grouped under other , and slash commands under custom . Useful for trends, useless for “is our new skill being used?”. Since October 22, the totals_by_skill , totals_by_custom_agent , totals_by_mcp , totals_by_slash_cmd and totals_by_plugin arrays show the configured name of your own items. Each list also holds up to 25 entries per record, up from five. Remark: names are reported from Copilot CLI, the Copilot app, clients built on the Copilot SDK (like VS Code ...
What does this method signature tell you? public Task<Order> GetOrder(Guid customerId, Guid orderId) Nothing that stops you from calling it like this: await repository.GetOrder(orderId, customerId); It compiles, it runs, and it returns nothing (or worse, the wrong thing). Every ID is a Guid , so the compiler can’t help you. This problem is called primitive obsession. We don't take real advantage of our type system but use any of the built-in primitives instead. The solution The obvious fix is a small wrapper type per ID. A readonly struct or a record does the job, but you end up writing the same boilerplate for every ID: equality, ToString , JSON serialization, a type converter for route binding, an EF Core value converter, Luckily someone already did all the hard work for us and created Vogen. Vogen is a source generator that does all the hard work. Add the package: dotnet add package Vogen And declare your ID: using Vogen; [ValueObject<Guid>]...