{"id":26109,"date":"2026-09-02T03:14:00","date_gmt":"2026-09-02T10:14:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/?p=26109"},"modified":"2026-09-02T03:14:00","modified_gmt":"2026-09-02T10:14:00","slug":"behind-spfx-dev-skills-testing-what-agents-know-and-fixing-what-they-miss","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/behind-spfx-dev-skills-testing-what-agents-know-and-fixing-what-they-miss\/","title":{"rendered":"Behind SPFx Dev Skills: testing what agents know and fixing what they miss"},"content":{"rendered":"<p>AI coding agents can build SharePoint Framework solutions. But should\nyou trust them to choose the right toolchain and package versions by\nthemselves, then apply every upgrade step correctly?<\/p>\n<p>We wanted evidence. Before publishing <a href=\"https:\/\/github.com\/SharePoint\/spfx-dev-skills\">SPFx Dev\nSkills<\/a>, the SharePoint Framework team and Developer Relations worked\ntogether to understand what agents already know and where they struggle.\nWe then measured which guidance improves the outcome.<\/p>\n<p>It\u2019s easy to package our expertise in a skill and tell developers to\ntrust it. Proving where the skill adds value takes more work, but\nproduces a far more useful result.<\/p>\n<h2>We started without the skill<\/h2>\n<p>The collaboration brought together Vesa Juvonen and Bert Jansen from\nthe OneDrive and SharePoint SPFx team, and Garry Trinder and Waldek\nMastykarz from Developer Relations. Collectively, we defined what a\ncorrect upgrade should look like and designed the evaluations, then\ntraced failures through the agents\u2019 complete sequence of actions.\nTogether, we turned those observations into changes across the surfaces\nthat agents use.<\/p>\n<p>The evaluations also built on years of work by the <a href=\"https:\/\/aka.ms\/cli-m365\">CLI for Microsoft 365<\/a> maintainers.\nThey have encoded deterministic, version-by-version SPFx upgrades in the\n<code>spfx project upgrade<\/code> command. We used that work as an input\nto our evaluations and, later, as the upgrade path we wanted agents to\ndiscover.<\/p>\n<p>Our first scenario focused on upgrading an SPFx 1.21.1 project to\n1.22.2. This requires more than changing package versions because SPFx\n1.22 introduced the move from gulp to Heft, along with related changes\nto configuration and the project structure.<\/p>\n<p>We asked GitHub Copilot Chat in Visual Studio Code on Windows, using\nClaude Sonnet 4.6 to do just that:<\/p>\n<pre class=\"text\"><code>Upgrade the project to 1.22.2<\/code><\/pre>\n<p>Notice that we purposefully didn\u2019t mention SPFx or point to\ndocumentation, and we ran the scenario without a skill. This gave us the\nbaseline: what can the agent do with the project context and its\nexisting knowledge?<\/p>\n<p>Because language models are non-deterministic, we ran the same\nscenario 5 times. We checked whether the project still built and ran,\nbut we also evaluated the details that distinguish a partial upgrade\nfrom a correct one.<\/p>\n<table>\n<thead>\n<tr>\n<th>Classification<\/th>\n<th style=\"text-align: right;\">Passed<\/th>\n<th style=\"text-align: right;\">Total<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Prerequisite<\/td>\n<td style=\"text-align: right;\">5<\/td>\n<td style=\"text-align: right;\">5<\/td>\n<\/tr>\n<tr>\n<td>Idiomatic use<\/td>\n<td style=\"text-align: right;\">7<\/td>\n<td style=\"text-align: right;\">10<\/td>\n<\/tr>\n<tr>\n<td>Dependency currency<\/td>\n<td style=\"text-align: right;\">34<\/td>\n<td style=\"text-align: right;\">50<\/td>\n<\/tr>\n<tr>\n<td>Configuration correctness<\/td>\n<td style=\"text-align: right;\">38<\/td>\n<td style=\"text-align: right;\">85<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Every run produced a project that passed our execution gates. At\nfirst glance, that looks like success. A closer look showed that the\nagent updated the headline SPFx version but missed dependencies and\nmigration details. Starting with a baseline kept us from writing a large\nskill that repeated knowledge the agent already had while missing the\nproblems that actually affected developers.<\/p>\n<h2>Copilot already knew a lot about SPFx<\/h2>\n<p>Before invoking a tool, the agent recognized the project as SPFx\nsimply from its file tree! It knew that Microsoft packages needed\nupdating and expected changes to the TypeScript toolchain. When it\nneeded the release notes, it didn\u2019t search for them. It constructed the\nfull Microsoft Learn URL directly, following the URL pattern established\nacross years of previous SPFx releases. Its weakness was combining that\nknowledge with the information it found.<\/p>\n<p>For example, an agent asked to upgrade to 1.22.2 fetched the release\nnotes for 1.22. It noticed that the documented version didn\u2019t exactly\nmatch the requested version, but didn\u2019t fetch every intermediate release\npage. That\u2019s risky because SPFx upgrades are incremental, so changes in\n1.22.0 and 1.22.1 still matter when the target is 1.22.2.<\/p>\n<p>The agent also formed its plan before reading the documentation, then\nused the docs to confirm it. A tip suggesting CLI for Microsoft 365\ndidn\u2019t change its approach because the page also offered detailed manual\nmigration steps that looked actionable.<\/p>\n<p>So, what should a skill add when the agent already recognizes SPFx\nand can find its docs? Precise decision rules for the places where\ngeneric knowledge is unreliable.<\/p>\n<h2>We tested the obvious answer<\/h2>\n<p>The SPFx team had already created a separate anti-hallucination\nskill. It instructed the agent to verify SPFx facts using authoritative\ndocumentation. We compared the baseline with this skill, then added the\ncontext7 MCP server to see whether another documentation source helped\nfurther.<\/p>\n<table>\n<colgroup>\n<col style=\"width: 20%;\" \/>\n<col style=\"width: 26%;\" \/>\n<col style=\"width: 26%;\" \/>\n<col style=\"width: 26%;\" \/> <\/colgroup>\n<thead>\n<tr>\n<th>Classification<\/th>\n<th style=\"text-align: right;\">Baseline<\/th>\n<th style=\"text-align: right;\">+ Anti-hallucination skill<\/th>\n<th style=\"text-align: right;\">+ Anti-hallucination skill and\ncontext7<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Prerequisite<\/td>\n<td style=\"text-align: right;\">5 \/ 5<\/td>\n<td style=\"text-align: right;\">5 \/ 5<\/td>\n<td style=\"text-align: right;\">5 \/ 5<\/td>\n<\/tr>\n<tr>\n<td>Idiomatic use<\/td>\n<td style=\"text-align: right;\">7 \/ 10<\/td>\n<td style=\"text-align: right;\">10 \/ 10<\/td>\n<td style=\"text-align: right;\">8 \/ 10<\/td>\n<\/tr>\n<tr>\n<td>Dependency currency<\/td>\n<td style=\"text-align: right;\">34 \/ 50<\/td>\n<td style=\"text-align: right;\">40 \/ 50<\/td>\n<td style=\"text-align: right;\">39 \/ 50<\/td>\n<\/tr>\n<tr>\n<td>Configuration correctness<\/td>\n<td style=\"text-align: right;\">38 \/ 85<\/td>\n<td style=\"text-align: right;\">46 \/ 85<\/td>\n<td style=\"text-align: right;\">47 \/ 85<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The anti-hallucination skill improved the results and reduced average\ntoken use by roughly 9%, but directing the agent to authoritative\ndocumentation still left the project only partially upgraded.<\/p>\n<p>Adding context7 didn\u2019t provide meaningful additional lift. In 3 of 5\nruns, its tools were available but never invoked. Availability alone\ndidn\u2019t make the tools relevant to the agent\u2019s plan.<\/p>\n<p>We had better numbers, but not enough to call the upgrade problem\nsolved. Treating the anti-hallucination skill as the answer would have\nbeen the agent-development equivalent of saying, <em>trust us, this\nhelps<\/em>, so we kept looking.<\/p>\n<h2>The best upgrade guidance already existed<\/h2>\n<p><a href=\"https:\/\/aka.ms\/cli-m365\">CLI for Microsoft 365<\/a> includes\nthe <code>spfx project upgrade<\/code> command. It analyzes the source\nand target versions, then generates the version-specific changes\nrequired for an incremental upgrade.<\/p>\n<p>When we explicitly told the agent to use the CLI, dependency currency\njumped from 34\/50 to 50\/50. Configuration correctness rose from 38\/85 to\n83\/85.<\/p>\n<table>\n<thead>\n<tr>\n<th>Classification<\/th>\n<th style=\"text-align: right;\">Baseline<\/th>\n<th style=\"text-align: right;\">+ CLI for Microsoft 365<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Prerequisite<\/td>\n<td style=\"text-align: right;\">5 \/ 5<\/td>\n<td style=\"text-align: right;\">5 \/ 5<\/td>\n<\/tr>\n<tr>\n<td>Idiomatic use<\/td>\n<td style=\"text-align: right;\">7 \/ 10<\/td>\n<td style=\"text-align: right;\">4 \/ 10<\/td>\n<\/tr>\n<tr>\n<td>Dependency currency<\/td>\n<td style=\"text-align: right;\">34 \/ 50<\/td>\n<td style=\"text-align: right;\">50 \/ 50<\/td>\n<\/tr>\n<tr>\n<td>Configuration correctness<\/td>\n<td style=\"text-align: right;\">38 \/ 85<\/td>\n<td style=\"text-align: right;\">83 \/ 85<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>An existing product tool produced the strongest results because it\nalready encoded the upgrade logic. The agent didn\u2019t discover it by\nitself, so we focused SPFx Dev Skills on guiding the agent to the CLI\nwhen an upgrade required it.<\/p>\n<h2>Documentation changed the agent\u2019s plan<\/h2>\n<p>The SPFx release notes already included a tip about CLI for Microsoft\n365. Even when we added the exact command, agents continued with their\nmanual plan.<\/p>\n<p>Why? Because a tip offers an alternative without telling the agent\nthat its current approach is wrong. Meanwhile, the linked migration\nguide contained detailed manual steps supported by npm commands and JSON\nsnippets. Agents consistently chose that actionable content.<\/p>\n<p>We used <a href=\"https:\/\/aka.ms\/devproxy\">Dev Proxy<\/a> to test\ndocumentation changes without publishing unproven ideas to Microsoft\nLearn. Several attempts didn\u2019t work. Moving the tip made no difference,\nand removing the migration guide hurt manual runs without reliably\nincreasing CLI adoption.<\/p>\n<p>Then we added a warning immediately before the tip, directly\nchallenging the agent\u2019s manual approach:<\/p>\n<blockquote><p>Upgrading from a previous minor version requires changes across\npackage versions, build configuration files, and toolchain settings that\nvary depending on your source version. Manually updating package.json\nalone will result in build failures.<\/p><\/blockquote>\n<p>With the detailed migration link removed, CLI adoption moved from 0\nof 5 runs to 5 of 5. The warning worked because it challenged the plan\nthe agent had already formed.<\/p>\n<p>We couldn\u2019t simply remove useful guidance for human readers, though.\nWhen we restored the step-by-step migration guide, CLI adoption fell\nback to 0 of 5. So we rewrote the guide to explain what changes during\nthe gulp-to-Heft migration while directing readers to CLI for Microsoft\n365 to apply those changes. With the conceptual guide supporting the\nwarning, agents used the CLI in 5 of 5 runs, and configuration\ncorrectness reached 85\/85.<\/p>\n<p>We submitted these improvements to the SPFx documentation. The\nrelease-note version changes shipped in <a href=\"https:\/\/github.com\/SharePoint\/sp-dev-docs\/pull\/10855\">PR\n#10855<\/a>, followed by the warning and rewritten migration guidance in\n<a href=\"https:\/\/github.com\/SharePoint\/sp-dev-docs\/pull\/10921\">PR\n#10921<\/a>. Putting these fixes at the source made them available to all\ndevelopers and agents, including those without SPFx Dev Skills.<\/p>\n<h2>The evaluation shaped SPFx Dev Skills<\/h2>\n<p>Our evaluation covered the upgrade scenario and compared several ways\nof helping the agent, including the separate anti-hallucination skill.\nThe results showed what SPFx Dev Skills should add and what it should\nleave to authoritative documentation or existing tools. The <a href=\"https:\/\/github.com\/SharePoint\/spfx-dev-skills\">SPFx Dev Skills<\/a>\npreview packages the SPFx-specific decision rules in 1 focused\n<code>spfx<\/code> skill and routes each request to a self-contained\nplaybook.<\/p>\n<p>Today, the skill covers these areas:<\/p>\n<ul>\n<li>creating SPFx web parts, extensions, libraries, and Adaptive Card\nExtensions;<\/li>\n<li>upgrading projects with CLI for Microsoft 365;<\/li>\n<li>choosing Heft for SPFx 1.22.0 and newer, or gulp for earlier\nversions;<\/li>\n<li>building React interfaces with Fluent UI v9; and<\/li>\n<li>using PnPjs for SharePoint and Microsoft Graph data access.<\/li>\n<\/ul>\n<p>The upgrade guidance reflects what we observed during evaluation. It\ntells the agent to detect the installed version and check Node and\nTypeScript compatibility before acting. The agent then uses CLI for\nMicrosoft 365 to apply every generated change in order, and it must\nfinish with a clean build. The global guidance also tells agents to run\nlong SPFx dependency installations synchronously, avoiding the repeated\nterminal polling we saw consume time and tokens during testing.<\/p>\n<p>The skill complements the documentation and CLI by helping the agent\nchoose the right source and use it correctly.<\/p>\n<p>SPFx Dev Skills is currently available in preview. Its playbooks for\ncreation and design extend beyond what we evaluated here, as do its\ntoolchain and data playbooks. We\u2019ll keep validating them through real\nusage, and developers should review the output before committing or\nshipping.<\/p>\n<h2>The collaboration improved more than the skill<\/h2>\n<p>The investigation also surfaced an opportunity beyond SPFx. Microsoft\nLearn supports returning pages directly as Markdown, giving agents\ncleaner content than converting the full HTML page. We shared this\nfinding with the GitHub Copilot teams, who added\n<code>Accept: text\/markdown<\/code> support to GitHub Copilot Chat and\nGitHub Copilot CLI.<\/p>\n<p>Agent experience problems can originate outside a skill. In this\ncase, some fixes belonged in documentation or the CLI, while another sat\nin the platform that retrieves content. Establishing the baseline showed\nus where to work.<\/p>\n<h2>Try the preview and help us improve it<\/h2>\n<p>You can explore <a href=\"https:\/\/github.com\/SharePoint\/spfx-dev-skills\">SPFx Dev Skills on\nGitHub<\/a>. The repository contains the portable <code>spfx<\/code> skill\nand its task-specific references, along with manual installation\ninstructions for compatible AI coding agents. Try the preview with your\nSPFx work and review what the agent produces. When the result is wrong\nor surprising, <a href=\"https:\/\/github.com\/SharePoint\/spfx-dev-skills\/issues\">open an\nissue<\/a>. That evidence will help us decide what the skill should teach\nnext, and what we should fix somewhere else.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How much guidance does an AI coding agent actually need? See how we used evaluation data to target SPFx knowledge gaps, improving results without wasting tokens on what models already know.<\/p>\n","protected":false},"author":74222,"featured_media":26116,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,166,9],"tags":[242,433,225,251,223,162,19,221],"class_list":["post-26109","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microsoft-365-developer","category-sharepoint","category-sharepoint-framework","tag-copilot","tag-mcp-apps","tag-microsoft-365","tag-microsoft-365-copilot","tag-microsoft-teams","tag-sharepoint","tag-sharepoint-framework","tag-spfx"],"acf":[],"blog_post_summary":"<p>How much guidance does an AI coding agent actually need? See how we used evaluation data to target SPFx knowledge gaps, improving results without wasting tokens on what models already know.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/26109","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/users\/74222"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/comments?post=26109"}],"version-history":[{"count":2,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/26109\/revisions"}],"predecessor-version":[{"id":26115,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/26109\/revisions\/26115"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media\/26116"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media?parent=26109"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/categories?post=26109"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/tags?post=26109"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}