<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Majdi Zlitni</title>
    <description>The latest articles on DEV Community by Majdi Zlitni (@majdizlitni).</description>
    <link>https://dev.to/majdizlitni</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F663655%2Fc25e42cd-b11f-44d6-845f-44d0014ba343.jpg</url>
      <title>DEV Community: Majdi Zlitni</title>
      <link>https://dev.to/majdizlitni</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/majdizlitni"/>
    <language>en</language>
    <item>
      <title>Playwright Agents The Architecture of Self-Healing</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Tue, 01 Sep 2026 12:22:25 +0000</pubDate>
      <link>https://dev.to/majdizlitni/playwright-agents-the-architecture-of-self-healing-2b97</link>
      <guid>https://dev.to/majdizlitni/playwright-agents-the-architecture-of-self-healing-2b97</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Playwright Agents (v1.56+) introduce three specialized agents &lt;strong&gt;Planner&lt;/strong&gt;, &lt;strong&gt;Generator&lt;/strong&gt;, and &lt;strong&gt;Healer&lt;/strong&gt; that run on the Model Context Protocol (MCP) to explore your app, write Markdown test plans, synthesize validated Playwright specs, and self-heal broken tests when the UI changes. This guide walks through the architecture, setup, a full worked example, and the ROI case for bringing this into an enterprise CI/CD pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TL;DR&lt;/li&gt;
&lt;li&gt;The problem with E2E testing today&lt;/li&gt;
&lt;li&gt;
1. The agentic testing triad

&lt;ul&gt;
&lt;li&gt;Why MCP matters here&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
2. What each agent actually does

&lt;ul&gt;
&lt;li&gt;🎭 Planner — the strategic test architect&lt;/li&gt;
&lt;li&gt;🎭 Generator — live-validated code synthesis&lt;/li&gt;
&lt;li&gt;🎭 Healer — autonomous runtime self-repair&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
3. Setting it up

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Initialize the agents&lt;/li&gt;
&lt;li&gt;Resulting project structure&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
4. Walkthrough: a movies catalog feature

&lt;ul&gt;
&lt;li&gt;Step 1 — write a deterministic seed fixture&lt;/li&gt;
&lt;li&gt;Step 2 — plan the feature with the Planner&lt;/li&gt;
&lt;li&gt;Step 3 — generate the executable test&lt;/li&gt;
&lt;li&gt;Step 4 — let the Healer fix what breaks&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
5. Is it worth it for an enterprise suite?

&lt;ul&gt;
&lt;li&gt;The ROI case&lt;/li&gt;
&lt;li&gt;Governance and security, non-negotiable&lt;/li&gt;
&lt;li&gt;Where it still needs a human&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Wrapping up&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The problem with E2E testing today
&lt;/h2&gt;

&lt;p&gt;End-to-end testing has always had the same three enemies: fragile locators, slow test authoring, and maintenance that eats a huge chunk of sprint velocity every time the UI changes. AI code assistants helped a little, but they generate code blind no access to the live DOM, no idea what actually renders in the browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Playwright Agents (v1.56+)&lt;/strong&gt; close that gap. Instead of "AI-assisted code generation," you get &lt;em&gt;agentic&lt;/em&gt; test automation: agents that operate inside a live execution loop, actually clicking through your app, reading the accessibility tree, and validating what they generate against the running page.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The agentic testing triad
&lt;/h2&gt;

&lt;p&gt;Three agents share one Model Context Protocol connection, each responsible for a different stage of the test lifecycle:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Core input&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Planner&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Seed fixture, app URL, requirements&lt;/td&gt;
&lt;td&gt;Navigates the app, maps user flows, considers edge cases&lt;/td&gt;
&lt;td&gt;Markdown test specs (&lt;code&gt;specs/*.md&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Generator&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Markdown plan + live browser context&lt;/td&gt;
&lt;td&gt;Executes actions live, validates locators, verifies assertions&lt;/td&gt;
&lt;td&gt;Executable spec files (&lt;code&gt;tests/*.spec.ts&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Healer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Failing test logs, trace artifacts, DOM snapshot&lt;/td&gt;
&lt;td&gt;Debugs step by step, evaluates selector changes, adjusts waits&lt;/td&gt;
&lt;td&gt;Patched, re-verified test files (or explicit skips)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Why MCP matters here
&lt;/h3&gt;

&lt;p&gt;MCP is what lets the LLM host VS Code Copilot Chat, Claude Code, OpenCode, whatever you're driving this from talk directly to the browser runtime instead of guessing at markup. Concretely, the agents read:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility tree snapshots&lt;/strong&gt; ARIA roles and accessible names instead of brittle CSS selectors or auto-generated XPaths&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network traces&lt;/strong&gt; XHR/fetch activity, so assertions can match real server-side state instead of just "something changed on screen"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Console and error diagnostics&lt;/strong&gt; stack traces and failed assertions, which is what the Healer uses to figure out &lt;em&gt;why&lt;/em&gt; a test broke
## 2. What each agent actually does&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🎭 Planner the strategic test architect
&lt;/h3&gt;

&lt;p&gt;The Planner doesn't write code first it writes a plan. It walks the live UI using a seed fixture you provide, then produces a structured Markdown spec with explicit preconditions, numbered steps, and expected outcomes. That Markdown is meant to be read and edited by a human before anything gets generated, which is the point: it's a review gate for QA leads, not a black box.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎭 Generator live-validated code synthesis
&lt;/h3&gt;

&lt;p&gt;The Generator turns that Markdown into runnable TypeScript. The key difference from a static code generator is that it validates every locator against the live DOM as it writes, preferring resilient selectors like &lt;code&gt;getByRole()&lt;/code&gt;, &lt;code&gt;getByLabel()&lt;/code&gt;, and &lt;code&gt;getByTestId()&lt;/code&gt;. It also looks at your existing fixtures and page objects so the generated code matches your project's conventions instead of reinventing them.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎭 Healer autonomous runtime self-repair
&lt;/h3&gt;

&lt;p&gt;When a test breaks because of a UI refactor, a DOM shift, changed test data, or timing the Healer reruns it in a managed debug environment, diffs the DOM snapshot against what the test expected, and patches the specific thing that changed: a selector, an assertion target, a wait. If the underlying feature is actually broken (not just relocated), it skips the test and flags it for a human instead of forcing a false pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Setting it up
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Node.js LTS (v20.x or higher)&lt;/li&gt;
&lt;li&gt;VS Code v1.105+ if you want native Copilot Chat agent integration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@playwright/test&lt;/code&gt; v1.56.0 or higher
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Confirm your Playwright version supports agents&lt;/span&gt;
npx playwright &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# Must be &amp;gt;= 1.56.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Initialize the agents
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;init-agents&lt;/code&gt; wires the agents into whichever execution loop you're using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Upgrade Playwright core&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; @playwright/test@latest

&lt;span class="c"&gt;# Bind to VS Code Copilot Chat&lt;/span&gt;
npx playwright init-agents &lt;span class="nt"&gt;--loop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vscode

&lt;span class="c"&gt;# Or bind to Claude Code&lt;/span&gt;
npx playwright init-agents &lt;span class="nt"&gt;--loop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;claude

&lt;span class="c"&gt;# Or bind to OpenCode&lt;/span&gt;
npx playwright init-agents &lt;span class="nt"&gt;--loop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;opencode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Resulting project structure
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcc40gx3sp2u07i3p5q3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcc40gx3sp2u07i3p5q3i.png" alt="Entreprise Playwright Suite" width="798" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Walkthrough: a movies catalog feature
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 write a deterministic seed fixture
&lt;/h3&gt;

&lt;p&gt;Seed files establish a known starting state auth, seeded data, starting route before any agent starts exploring.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tests/seed.spec.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;listTest&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./helpers/list-test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Seed context for authenticated movie management operations.
 * Copied by the Generator into every synthesized test file.
 */&lt;/span&gt;
&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Seed context: Logged-in administrator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Initialize movies list fixture&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;listPage&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;listPage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;heading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Movie Catalog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 plan the feature with the Planner
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@planner Generate a comprehensive test plan for the "Adding a Movie" and
"Managing Movie Catalog" features. Use tests/seed.spec.ts as the entry seed context.
Save the output spec to specs/movies-list-plan.md.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Planner explores the app and produces something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Test Plan: Movies Catalog Management&lt;/span&gt;

&lt;span class="gu"&gt;## Context &amp;amp; Prerequisites&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Seed Context:**&lt;/span&gt; &lt;span class="sb"&gt;`tests/seed.spec.ts`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**User Role:**&lt;/span&gt; Authenticated Administrator

&lt;span class="gu"&gt;## Test Scenarios&lt;/span&gt;

&lt;span class="gu"&gt;### 1. Adding a New Movie Entry&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Preconditions:**&lt;/span&gt; Catalog loaded, add button accessible.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Steps:**&lt;/span&gt;
&lt;span class="p"&gt;  1.&lt;/span&gt; Click "Add Movie" primary action button.
&lt;span class="p"&gt;  2.&lt;/span&gt; Fill "Title", "Genre", and "Release Date" input fields.
&lt;span class="p"&gt;  3.&lt;/span&gt; Submit the form via "Save Movie" button.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Expected Results:**&lt;/span&gt;
&lt;span class="p"&gt;  -&lt;/span&gt; Form dialog closes.
&lt;span class="p"&gt;  -&lt;/span&gt; Toast notification displays a success message.
&lt;span class="p"&gt;  -&lt;/span&gt; New movie record appears in the grid view.

&lt;span class="gu"&gt;### 2. Catalog Validation &amp;amp; Boundary Constraints&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Steps:**&lt;/span&gt;
&lt;span class="p"&gt;  1.&lt;/span&gt; Submit "Add Movie" form with empty mandatory fields.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Expected Results:**&lt;/span&gt;
&lt;span class="p"&gt;  -&lt;/span&gt; Inline validation highlights missing title and release year.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 generate the executable test
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@generator Generate Playwright TypeScript test files based on the scenarios defined in
specs/movies-list-plan.md under section "Adding a New Movie Entry".
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tests/movies/add-movie.spec.ts&lt;/span&gt;
&lt;span class="c1"&gt;// spec: specs/movies-list-plan.md&lt;/span&gt;
&lt;span class="c1"&gt;// seed: tests/seed.spec.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;listTest&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../helpers/list-test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Movies Catalog Management&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adding a New Movie Entry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;listPage&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;listPage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Step 1: Click "Add Movie" primary action button&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addMovieBtn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Add Movie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addMovieBtn&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;addMovieBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Step 2: Fill mandatory fields using resilient ARIA-based locators&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Movie Title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Inception&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Genre&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;selectOption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sci-Fi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Release Year&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2010&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Step 3: Submit the form&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Save Movie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Assertions: confirm UI response and grid update&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toContainText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Movie successfully added&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cell&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Inception&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nf"&gt;toBeVisible&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4 let the Healer fix what breaks
&lt;/h3&gt;

&lt;p&gt;Say the "Add Movie" button gets renamed to "Create New Entry." The suite fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx playwright &lt;span class="nb"&gt;test &lt;/span&gt;tests/movies/add-movie.spec.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Invoke the Healer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@healer Run and fix the failing test in tests/movies/add-movie.spec.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It reruns the test in a debug session, diffs the accessibility tree, finds the renamed control, and patches the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// HEALED BY PLAYWRIGHT HEALER AGENT (v1.56)&lt;/span&gt;
&lt;span class="c1"&gt;// Original selector: page.getByRole('button', { name: 'Add Movie' })&lt;/span&gt;
&lt;span class="c1"&gt;// Updated to match the current accessible element:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addMovieBtn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Create New Entry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;addMovieBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Is it worth it for an enterprise suite?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The ROI case
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Traditional automation&lt;/th&gt;
&lt;th&gt;Playwright agentic workflow&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Test creation velocity&lt;/td&gt;
&lt;td&gt;2–4 hours per complex flow&lt;/td&gt;
&lt;td&gt;15–30 minutes (plan + generate)&lt;/td&gt;
&lt;td&gt;~75% faster authoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance overhead&lt;/td&gt;
&lt;td&gt;High locator upkeep eats sprint time&lt;/td&gt;
&lt;td&gt;Low Healer handles most repairs&lt;/td&gt;
&lt;td&gt;~65% less maintenance time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Locator quality&lt;/td&gt;
&lt;td&gt;Depends on developer discipline&lt;/td&gt;
&lt;td&gt;Standardized, accessibility-first&lt;/td&gt;
&lt;td&gt;Fewer flaky tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exploratory coverage&lt;/td&gt;
&lt;td&gt;Limited by manual capacity&lt;/td&gt;
&lt;td&gt;Expanded by autonomous Planner exploration&lt;/td&gt;
&lt;td&gt;Roughly 3.5x more scenarios covered&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These numbers will vary by codebase and team, but the direction is consistent: less time spent re-fixing selectors, more time spent on actual test strategy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Governance and security, non-negotiable
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Never hardcode secrets.&lt;/strong&gt; Inject credentials from environment variables or a vault:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;E2E_TEST_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Watch what leaves your network.&lt;/strong&gt; If you're on a public LLM endpoint, application metadata and test code are part of the prompt context. Use a local model, an Azure OpenAI instance, or an enterprise Copilot tenant if that's a concern.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Review everything.&lt;/strong&gt; Treat generated and healed tests like any other code change require a PR review before merging.&lt;/p&gt;
&lt;h3&gt;
  
  
  Where it still needs a human
&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complex business logic&lt;/strong&gt; deep financial calculations and domain-specific workflows need explicit human-designed test boundaries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Adversarial security testing&lt;/strong&gt; these agents validate expected paths, not attack surfaces. They are not a substitute for penetration testing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Visual and UX nuance&lt;/strong&gt; the agents check for presence and correct attributes, not whether something &lt;em&gt;looks&lt;/em&gt; right.&lt;/p&gt;
&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Playwright Agents don't replace test strategy they replace the tedious parts of it: writing boilerplate steps, chasing broken selectors, and re-authoring the same flows by hand. The Planner keeps humans in the loop before code exists; the Generator keeps the code honest against the live app; the Healer keeps the suite green without silently hiding real regressions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want to try it on your own project:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upgrade to &lt;code&gt;@playwright/test ^1.56.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Write one solid seed fixture (&lt;code&gt;tests/seed.spec.ts&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Pick a single critical flow login, checkout, registration and run &lt;code&gt;@planner&lt;/code&gt; then &lt;code&gt;@generator&lt;/code&gt; on it.&lt;/li&gt;
&lt;li&gt;Require PR review on anything the agents produce or heal.
If you try this on a real suite, I'd genuinely like to hear how the Healer holds up against your actual UI churn drop a comment below.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Agent Skills and how to use them</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Sat, 29 Aug 2026 17:00:46 +0000</pubDate>
      <link>https://dev.to/majdizlitni/agent-skills-and-how-to-use-them-46hb</link>
      <guid>https://dev.to/majdizlitni/agent-skills-and-how-to-use-them-46hb</guid>
      <description>&lt;p&gt;If your AI assistant keeps giving generic, unreliable answers, the problem is not the model. It is the missing structure around it. That is exactly what Agent Skills solve.&lt;/p&gt;

&lt;p&gt;Modern LLMs are strong enough to handle complex tasks. The real issue is that they are working without stable context, rules, or domain-specific instructions that guide how they should behave in your environment.&lt;/p&gt;

&lt;p&gt;This is where Agent Skills change the equation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjtpc743r2agzy5s2riac.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjtpc743r2agzy5s2riac.gif" alt="Agents" width="245" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Agent Skills Overview&lt;/li&gt;
&lt;li&gt;Why Agent Skills?&lt;/li&gt;
&lt;li&gt;How Do Agent Skills Work?&lt;/li&gt;
&lt;li&gt;Start from real expertise&lt;/li&gt;
&lt;li&gt;Project skills vs personal skills&lt;/li&gt;
&lt;li&gt;How Copilot uses agent skills&lt;/li&gt;
&lt;li&gt;Creating and adding a skill&lt;/li&gt;
&lt;li&gt;Example SKILL.md file&lt;/li&gt;
&lt;li&gt;Triggering a skill in VS Code&lt;/li&gt;
&lt;li&gt;Skills vs custom instructions&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Agent Skills Overview
&lt;/h2&gt;

&lt;p&gt;Agent skills are instructions and resources that a model can use for a given task to improve its output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgzokni1w4t3znvoo179f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgzokni1w4t3znvoo179f.gif" alt="Working agent" width="402" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agent skills are designed to work with modern AI coding assistants and LLM-based agents. While our current implementation leverages GitHub Copilot across tools like VS Code and CLI workflows, the architecture remains provider-agnostic and can be adapted to any compatible AI platform.&lt;/p&gt;

&lt;p&gt;You can create your own skills so an agent can perform tasks in a specific way.&lt;/p&gt;

&lt;p&gt;You can use both skills and custom instructions to teach Copilot how to work in your repository and how to perform specific tasks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Agent Skills?
&lt;/h2&gt;

&lt;p&gt;Agents are massively capable, but often they don't have the needed context for more reliable output. Using skills we can solve this by packaging user-specific context into a portable version an agent can load on demand so agents can be:&lt;/p&gt;

&lt;p&gt;Domain expertise: Capture specialized knowledge as reusable instructions and resources.&lt;br&gt;&lt;br&gt;
Repeatable workflows: Turn multi-step tasks into consistent, auditable procedures.&lt;br&gt;&lt;br&gt;
Cross-product reuse: Build a skill once and use it across any skills-compatible agent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe7dbyakils6cynyldm2b.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe7dbyakils6cynyldm2b.gif" alt="Brain to Brain" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  How Do Agent Skills Work?
&lt;/h2&gt;

&lt;p&gt;Agents load skills in three stages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discovery&lt;/strong&gt;: At startup, agents load only the name and description of each available skill, just enough to know when it might be relevant.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Activation&lt;/strong&gt;: When a task matches a skill's description, the agent reads the full SKILL.md instructions into context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Execution&lt;/strong&gt;: The agent follows the instructions, optionally executing bundled code or loading referenced files as needed.&lt;/p&gt;

&lt;p&gt;Full instructions load only when a task calls for them, so agents can keep many skills on hand with only a small context footprint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh1a3wjxraz6syvd9z8ft.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh1a3wjxraz6syvd9z8ft.gif" alt="Confused Pulp Fiction" width="426" height="213"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Start from real expertise
&lt;/h2&gt;

&lt;p&gt;A common pitfall in skill creation is asking an LLM to generate a skill without providing domain-specific context, relying solely on the LLM’s general training knowledge. The result is vague, generic procedures (“handle errors appropriately,” “follow best practices for authentication”) rather than the specific API patterns, edge cases, and project conventions that make a skill valuable.&lt;/p&gt;

&lt;p&gt;Effective skills are grounded in real expertise. The key is feeding domain-specific context into the creation process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwjcbflvz44j1bxqnkazh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwjcbflvz44j1bxqnkazh.gif" alt="feeding" width="540" height="360"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Project skills vs personal skills
&lt;/h2&gt;

&lt;p&gt;Project skills, stored in your repository (.github/skills, .claude/skills, or .agents/skills)&lt;br&gt;&lt;br&gt;
Personal skills, stored in your home directory and shared across projects (~/.copilot/skills or ~/.agents/skills)&lt;/p&gt;


&lt;h2&gt;
  
  
  How Copilot uses agent skills
&lt;/h2&gt;

&lt;p&gt;When performing tasks, Copilot will decide when to use your skills based on your prompt and the skill's description.&lt;/p&gt;

&lt;p&gt;When Copilot chooses to use a skill, the SKILL.md file will be injected in the agent's context, giving the agent access to your instructions. It can then follow those instructions and use any scripts or examples you may have included in the skill's directory.&lt;/p&gt;

&lt;p&gt;For Copilot code review on GitHub:&lt;/p&gt;

&lt;p&gt;If you want to ensure Copilot code review uses a skill, place it in a review-focused directory like &lt;code&gt;code-review&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Skills in &lt;code&gt;.github/skills&lt;/code&gt; can also be picked up automatically when relevant.&lt;/p&gt;


&lt;h2&gt;
  
  
  Creating and adding a skill
&lt;/h2&gt;

&lt;p&gt;To create an agent skill, you write a &lt;code&gt;SKILL.md&lt;/code&gt; file and optionally add supporting files like scripts or examples.&lt;/p&gt;

&lt;p&gt;Create a skills directory in one of these locations:&lt;/p&gt;

&lt;p&gt;Project skills:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.github/skills  
.claude/skills  
.agents/skills  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Personal skills:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.copilot/skills  
~/.agents/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each skill must live in its own folder:&lt;br&gt;
&lt;code&gt;.github/skills/webapp-testing&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Folder names must be lowercase and use hyphens.&lt;/p&gt;

&lt;p&gt;Inside it, create &lt;code&gt;SKILL.md&lt;/code&gt;.&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;Important&lt;/p&gt;

&lt;p&gt;Skill files must be named &lt;code&gt;SKILL.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It must include:&lt;/p&gt;

&lt;p&gt;YAML frontmatter:&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name (required)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lowercase identifier matching folder name&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;description (required)&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;when the skill should be used&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;license (optional)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Markdown body:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Instructions
- Examples
- Guidelines for the agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Example SKILL.md file
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;resume-update&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use this skill when the user asks to update, rewrite, or tailor a resume for a job application.&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="c1"&gt;# Resume Update Skill&lt;/span&gt;

&lt;span class="c1"&gt;## Instructions&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Rewrite resumes based on job description&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Improve clarity and structure&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Use concise bullet points&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Highlight relevant skills and achievements&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Keep it ATS-friendly&lt;/span&gt;

&lt;span class="c1"&gt;## Example&lt;/span&gt;
&lt;span class="na"&gt;User&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update my resume for a .NET backend role&lt;/span&gt;  
&lt;span class="na"&gt;Assistant&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Returns a rewritten resume emphasizing .NET, APIs, and backend experience.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Triggering a skill in VS Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option 1: Natural language
&lt;/h3&gt;

&lt;p&gt;Just ask normally:&lt;/p&gt;

&lt;p&gt;Help me update my resume for a .NET backend role&lt;/p&gt;

&lt;p&gt;If skill matches description → it auto-loads&lt;/p&gt;




&lt;h3&gt;
  
  
  Option 2: Slash command
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/resume-update
/webapp-testing
/github-actions-debugging

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also add extra context:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/resume-update for senior backend role&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  SKILL.md structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;skill-name&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;When and why this skill should be used&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="na"&gt;Then markdown instructions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="c1"&gt;### Instructions&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Step &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Step &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Step &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Skills vs custom instructions
&lt;/h2&gt;

&lt;p&gt;We recommend using custom instructions for simple instructions relevant to almost every task (for example information about your repository's coding standards), and skills for more detailed instructions that Copilot should only access when relevant.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>llm</category>
    </item>
    <item>
      <title>10 EF Core Performance Mistakes That Ship to Production</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Wed, 26 Aug 2026 16:16:05 +0000</pubDate>
      <link>https://dev.to/majdizlitni/10-ef-core-performance-mistakes-that-ship-to-production-1gpc</link>
      <guid>https://dev.to/majdizlitni/10-ef-core-performance-mistakes-that-ship-to-production-1gpc</guid>
      <description>&lt;p&gt;If your API is fast with seed data but slows down in production, EF Core is rarely the root cause. It is usually the amplifier.&lt;/p&gt;

&lt;p&gt;Most teams do not have one catastrophic query. They have many small query-shape decisions that compound into high P95 latency, lock pressure, and unnecessary database scale-up.&lt;/p&gt;

&lt;p&gt;This article is a practical field guide to 10 EF Core performance mistakes I keep seeing in production .NET APIs, and the fixes that usually move the needle first.&lt;/p&gt;

&lt;h2&gt;
  
  
  In this post
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Why this matters in production&lt;/li&gt;
&lt;li&gt;How to spot issues fast&lt;/li&gt;
&lt;li&gt;Architecture map of the anti-patterns&lt;/li&gt;
&lt;li&gt;Quick summary of all 10 mistakes&lt;/li&gt;
&lt;li&gt;Mistake 1: N+1 Queries&lt;/li&gt;
&lt;li&gt;Mistake 2: Missing AsNoTracking&lt;/li&gt;
&lt;li&gt;Mistake 3: Loading Whole Entities&lt;/li&gt;
&lt;li&gt;Mistake 4: No Pagination&lt;/li&gt;
&lt;li&gt;Mistake 5: Client-Side Evaluation&lt;/li&gt;
&lt;li&gt;Mistake 6: Tracking Read-Only Data&lt;/li&gt;
&lt;li&gt;Mistake 7: Cartesian Explosion&lt;/li&gt;
&lt;li&gt;Mistake 8: No Compiled Queries&lt;/li&gt;
&lt;li&gt;Mistake 9: Missing Indexes&lt;/li&gt;
&lt;li&gt;Mistake 10: SaveChanges in a Loop&lt;/li&gt;
&lt;li&gt;Batch ops caveat: ExecuteUpdate and ExecuteDelete&lt;/li&gt;
&lt;li&gt;Decision matrix: what to fix first&lt;/li&gt;
&lt;li&gt;What EF Core 10 improves&lt;/li&gt;
&lt;li&gt;Troubleshooting checklist&lt;/li&gt;
&lt;li&gt;Production baseline checklist&lt;/li&gt;
&lt;li&gt;Wrap-up&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What counts as a performance mistake?
&lt;/h2&gt;

&lt;p&gt;An EF Core performance mistake is any data-access pattern that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;returns correct results in development&lt;/li&gt;
&lt;li&gt;passes tests&lt;/li&gt;
&lt;li&gt;but degrades badly under real data volume or concurrency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words: correctness is not enough. Query shape is architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to detect issues quickly
&lt;/h2&gt;

&lt;p&gt;Before changing code, instrument first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseNpgsql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Information&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableSensitiveDataLogging&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use this as your first pass:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;many SELECTs per request: likely N+1&lt;/li&gt;
&lt;li&gt;huge result row count for small parent set: likely cartesian explosion&lt;/li&gt;
&lt;li&gt;read endpoints with heavy tracking snapshots: missing AsNoTracking&lt;/li&gt;
&lt;li&gt;list endpoints without LIMIT/TOP: missing pagination&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The anti-pattern map
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsa11r4dbbvc2cfq01etw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsa11r4dbbvc2cfq01etw.png" alt="EF Core anti-pattern architecture map" width="510" height="1846"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Prefer scalable quality for sharing and zoom:&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;The 10 mistakes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;N+1 queries&lt;/li&gt;
&lt;li&gt;Loading full entities instead of projections&lt;/li&gt;
&lt;li&gt;Missing AsNoTracking on read paths&lt;/li&gt;
&lt;li&gt;No pagination on list endpoints&lt;/li&gt;
&lt;li&gt;Client-side evaluation patterns&lt;/li&gt;
&lt;li&gt;Tracking read-only graphs&lt;/li&gt;
&lt;li&gt;Cartesian explosion from multiple collection Includes&lt;/li&gt;
&lt;li&gt;No compiled queries on hot paths&lt;/li&gt;
&lt;li&gt;Missing indexes on hot filters and joins&lt;/li&gt;
&lt;li&gt;SaveChanges inside loops&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Plus one operational caveat: ExecuteUpdate and ExecuteDelete bypass the change tracker and should be coordinated with explicit transaction boundaries when mixed with tracked changes.&lt;/p&gt;

&lt;p&gt;&lt;a id="mistake-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1) N+1 Queries
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;You load a parent set, then each navigation access triggers another database round trip.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smell
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Request count looks normal&lt;/li&gt;
&lt;li&gt;SQL command count explodes&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Use projection or eager loading intentionally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomerId&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;OrderDto&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Total&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Quantity&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;ItemCount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use projection for API contracts. Use Include when domain logic needs full related aggregates in memory.&lt;/p&gt;

&lt;p&gt;&lt;a id="mistake-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Missing AsNoTracking
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Tracking every entity in read paths increases memory and CPU for change detection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Default to no tracking on query endpoints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Posts&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTracking&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OrderByDescending&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PublishedAt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For write paths, opt back in explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsTracking&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a id="mistake-3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Loading Whole Entities
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Fetching full rows when you only need 2-3 columns inflates payload and materialization cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Project to DTOs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTracking&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UserListItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DisplayName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AvatarUrl&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Projection usually improves all of these at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;less SQL payload&lt;/li&gt;
&lt;li&gt;lower materialization cost&lt;/li&gt;
&lt;li&gt;better API boundary control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="mistake-4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4) No Pagination
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Unbounded lists eventually become accidental load tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Apply deterministic ordering and pagination.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Articles&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTracking&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OrderByDescending&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreatedAt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Skip&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Page&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PageSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PageSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Always cap server-side page size to prevent accidental heavy requests.&lt;/p&gt;

&lt;p&gt;&lt;a id="mistake-5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5) Client-Side Evaluation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Non-translatable logic forces EF Core to pull data and evaluate in memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Keep filters SQL-translatable, move complex logic after narrowing rows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;filtered&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Payments&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTracking&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;PaymentStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Settled&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reference&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rule: filter, sort, and paginate before materialization. Terminal operators like ToListAsync end translation and execute the query.&lt;/p&gt;

&lt;p&gt;&lt;a id="mistake-6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6) Tracking Read-Only Data
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Long-running request flows with tracked entities increase memory pressure and GC churn.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Use one of these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AsNoTracking for pure reads&lt;/li&gt;
&lt;li&gt;AsNoTrackingWithIdentityResolution when graph identity consistency matters
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTrackingWithIdentityResolution&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use AsNoTrackingWithIdentityResolution when you need consistent identity for repeated references in the same result graph without full tracking overhead.&lt;/p&gt;

&lt;p&gt;&lt;a id="mistake-7"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7) Cartesian Explosion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Multiple collection Includes on one query create row multiplication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Use split queries when shape is unavoidable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTracking&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsSplitQuery&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Split queries trade one huge cross-product for multiple smaller round trips. Measure both modes on your dataset.&lt;/p&gt;

&lt;p&gt;&lt;a id="mistake-8"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8) No Compiled Queries
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Hot endpoints repeatedly pay query translation overhead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Precompile stable high-frequency queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;GetUserByIdCompiled&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;EF&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CompileAsyncQuery&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTracking&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;GetUserByIdCompiled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply compiled queries selectively to the highest-throughput read paths.&lt;/p&gt;

&lt;p&gt;&lt;a id="mistake-9"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9) Missing Indexes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Critical filters run as scans instead of seeks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Create indexes for common predicates and sort keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;modelBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HasIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreatedAt&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also verify generated SQL and query plan. If your API filter is index-friendly but still scanning, check collation mismatches and implicit conversions.&lt;/p&gt;

&lt;p&gt;Index guidance for hot endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;index frequent WHERE columns&lt;/li&gt;
&lt;li&gt;index JOIN keys&lt;/li&gt;
&lt;li&gt;index ORDER BY columns used with pagination&lt;/li&gt;
&lt;li&gt;prefer composite indexes that match filter plus sort order&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a id="mistake-10"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  10) SaveChanges in a Loop
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Each SaveChanges call is a round trip and transaction boundary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Batch entity changes, then persist once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MarkProcessed&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveChangesAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this runs inside import or reconciliation jobs, moving SaveChanges out of the loop is often the fastest immediate win.&lt;/p&gt;

&lt;p&gt;&lt;a id="batch-ops-caveat"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Batch operations caveat: ExecuteUpdate and ExecuteDelete
&lt;/h2&gt;

&lt;p&gt;ExecuteUpdate and ExecuteDelete bypass the change tracker.&lt;/p&gt;

&lt;p&gt;If you mix them with tracked updates in the same unit of work, wrap all operations in an explicit transaction to protect consistency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BeginTransactionAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;OrderStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pending&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreatedAt&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;cutoff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExecuteUpdateAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;setters&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;setters&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OrderStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Expired&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;audit&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;CleanupAudit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;RanAtUtc&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Affected&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;affectedRows&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CleanupAudits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveChangesAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CommitAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why this matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;batch operators bypass change tracker&lt;/li&gt;
&lt;li&gt;SaveChanges interceptors may not run for those operations&lt;/li&gt;
&lt;li&gt;mixed write workflows should be explicit about consistency boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Decision matrix: what to fix first
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;First fix&lt;/th&gt;
&lt;th&gt;Then&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;many SQL commands per request&lt;/td&gt;
&lt;td&gt;projection or Include cleanup&lt;/td&gt;
&lt;td&gt;check for lazy loading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;large payload and high serialization cost&lt;/td&gt;
&lt;td&gt;projection DTOs&lt;/td&gt;
&lt;td&gt;AsNoTracking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;high read-path memory&lt;/td&gt;
&lt;td&gt;AsNoTracking&lt;/td&gt;
&lt;td&gt;query-level projection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;huge row count from multi-Include&lt;/td&gt;
&lt;td&gt;AsSplitQuery&lt;/td&gt;
&lt;td&gt;endpoint-specific projection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;slow large updates/deletes&lt;/td&gt;
&lt;td&gt;ExecuteUpdate/ExecuteDelete&lt;/td&gt;
&lt;td&gt;transaction + audit strategy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;list endpoint timeout&lt;/td&gt;
&lt;td&gt;pagination&lt;/td&gt;
&lt;td&gt;indexes + projection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hot endpoint CPU overhead&lt;/td&gt;
&lt;td&gt;compiled query&lt;/td&gt;
&lt;td&gt;caching strategy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What EF Core 10 helps with
&lt;/h2&gt;

&lt;p&gt;EF Core 10 improves the baseline, but does not remove bad query-shape costs.&lt;/p&gt;

&lt;p&gt;Useful platform gains to leverage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;improved LINQ ergonomics for complex joins&lt;/li&gt;
&lt;li&gt;stronger behavior around split-query ordering consistency&lt;/li&gt;
&lt;li&gt;runtime improvements in .NET 10 that help materialization paths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bottom line: framework improvements help good patterns more than bad ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting checklist
&lt;/h2&gt;

&lt;p&gt;If performance is still poor after applying fixes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;inspect SQL plans, not just LINQ&lt;/li&gt;
&lt;li&gt;verify index usage in production-like data&lt;/li&gt;
&lt;li&gt;confirm no hidden lazy-loading path in serialization&lt;/li&gt;
&lt;li&gt;verify query count per request in high-traffic endpoints&lt;/li&gt;
&lt;li&gt;re-check page size limits and default sort columns&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A practical baseline for production APIs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Default reads to no tracking&lt;/li&gt;
&lt;li&gt;Project to DTOs, not entities&lt;/li&gt;
&lt;li&gt;Always paginate collection endpoints&lt;/li&gt;
&lt;li&gt;Measure query count per request&lt;/li&gt;
&lt;li&gt;Add indexes for every top-traffic filter&lt;/li&gt;
&lt;li&gt;Compile truly hot queries&lt;/li&gt;
&lt;li&gt;Avoid SaveChanges inside loops&lt;/li&gt;
&lt;li&gt;Treat batch operations as transaction-sensitive writes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;EF Core performance is rarely about a single trick. It is about query-shape discipline applied consistently.&lt;/p&gt;

&lt;p&gt;If your P95 latency is climbing, start here before scaling the database tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;Most EF Core incidents are not caused by obscure ORM bugs. They come from convenient defaults used past their safe limits.&lt;/p&gt;

&lt;p&gt;If you adopt one rule, make it this: shape data intentionally at query time. Projection, no-tracking reads, pagination, and index-aware filters will solve most production regressions before you need heavier architecture changes.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>efcore</category>
      <category>performance</category>
    </item>
    <item>
      <title>Effective AI Agents with GitHub Copilot</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Mon, 24 Aug 2026 16:44:08 +0000</pubDate>
      <link>https://dev.to/majdizlitni/effective-ai-agents-with-github-copilot-4ck7</link>
      <guid>https://dev.to/majdizlitni/effective-ai-agents-with-github-copilot-4ck7</guid>
      <description>&lt;p&gt;The most successful AI agent do NOT use complex and over-engineered frameworks. Instead, they use simple, modular patterns.&lt;/p&gt;

&lt;p&gt;To use agents you don't need to learn massive third-party agent frameworks to build powerful AI assistants. Using GitHub Copilot you get all pieces natively: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copilot Agent Mode&lt;/li&gt;
&lt;li&gt;Custom Agents &lt;/li&gt;
&lt;li&gt;Agent Skills &lt;/li&gt;
&lt;li&gt;Prompt Files&lt;/li&gt;
&lt;li&gt;Model Context Protocol (MCP)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will break down the core principles on how to implement them in your daily development workflow!&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What is an AI Agent?&lt;/li&gt;
&lt;li&gt;
How Effective Agents Work

&lt;ul&gt;
&lt;li&gt;Pattern 1: Prompt Chaining&lt;/li&gt;
&lt;li&gt;Pattern 2: Routing&lt;/li&gt;
&lt;li&gt;Pattern 3: Parallelization&lt;/li&gt;
&lt;li&gt;Pattern 4: Orchestrator Workers The Project Manager&lt;/li&gt;
&lt;li&gt;Pattern 5: Evaluator Optimizer&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Handoffs Between Agents

&lt;ul&gt;
&lt;li&gt;Why Single Agents Fail&lt;/li&gt;
&lt;li&gt;Architect to Developer Handoff&lt;/li&gt;
&lt;li&gt;Preserving Context Across Handoffs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Mastering Agent Skills

&lt;ul&gt;
&lt;li&gt;The Copilot Customization Pyramid&lt;/li&gt;
&lt;li&gt;
What is an Agent Skill? &lt;/li&gt;
&lt;li&gt;Integrating External Systems via MCP&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Quick Comparison Matrix
&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. What is an AI Agent?
&lt;/h2&gt;

&lt;p&gt;Before we dive, let's clear up what an &lt;strong&gt;Agent&lt;/strong&gt; actually is. &lt;/p&gt;

&lt;p&gt;An agent is as a fully autonomous system using different tools to achieve a request independently&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxfrzvzr5nnl5kcv5fjlv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxfrzvzr5nnl5kcv5fjlv.png" alt="Agent" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Basic Building Block
&lt;/h3&gt;

&lt;p&gt;An &lt;strong&gt;Augmented LLM&lt;/strong&gt; is simply a language model (like GPT-5.6 Luna or Claude Opus) connected to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Context&lt;/strong&gt;: Your project's code files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt;: The ability to run commands and execute tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory&lt;/strong&gt;: The chat history.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In GitHub Copilot, every query you send has access to these augmentations natively inside your IDE!&lt;/p&gt;




&lt;h2&gt;
  
  
  2. How Effective Agents Work
&lt;/h2&gt;

&lt;p&gt;Rather than letting an AI run completely wild, effective agentic systems use one of the folowing core design patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 1: Prompt Chaining
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzyq6ruhx3p2kujjxg7df.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzyq6ruhx3p2kujjxg7df.png" alt="Effective Agents" width="800" height="163"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; Breaking a big task into a sequence of small, step-by-step prompts. Between each step, code execution acts as a &lt;strong&gt;Gate&lt;/strong&gt; to verify output before moving to the next step.&lt;br&gt;
This can be achieved by: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a reusable prompt file inside &lt;code&gt;.github/prompts/create-feature.prompt.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- .github/prompts/create-feature.prompt.md --&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;1.&lt;/span&gt; Read the user requirements and generate the Entity Framework Core model in &lt;span class="sb"&gt;`Domain/Entities/`&lt;/span&gt;.
&lt;span class="p"&gt;2.&lt;/span&gt; Run &lt;span class="sb"&gt;`dotnet build`&lt;/span&gt; in the terminal to verify zero compilation errors.
&lt;span class="p"&gt;3.&lt;/span&gt; If build succeeds, create the corresponding DTO class in &lt;span class="sb"&gt;`Application/DTOs/`&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Pattern 2: Routing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx7xkiyn2p5i05ch9srhk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx7xkiyn2p5i05ch9srhk.png" alt="the Router" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It classifying the user's intent and sending the request to a specialized assistant or tool.&lt;/p&gt;

&lt;p&gt;Using GitHub Copilot's &lt;code&gt;@&lt;/code&gt; participants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@workspace&lt;/code&gt;: Searches your entire codebase structure.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@azure&lt;/code&gt;: Handles cloud infrastructure questions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@github&lt;/code&gt;: Interacts with PRs, issues, and actions.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Pattern 3: Parallelization
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9pbbs85t6a2e298d8wh8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9pbbs85t6a2e298d8wh8.png" alt="Agent Parallelization" width="799" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This run multiple AI checks simultaneously and combining their output into a single summary.&lt;/p&gt;

&lt;p&gt;When running automated GitHub Actions or code reviews, trigger multiple custom prompts in parallel (e.g., checking security flaws, checking unit test coverage, checking formatting) and combine the results.&lt;/p&gt;




&lt;h3&gt;
  
  
  Pattern 4: Orchestrator Workers The Project Manager
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgwff6p6kwfyx5gtoc402.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgwff6p6kwfyx5gtoc402.png" alt="Orchestrator-Workers" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A central agent dynamically breaks a complex, unpredictable request into sub-tasks, delegates work to specialized agents or tool steps, and combines the results.&lt;/p&gt;

&lt;p&gt;This is exactly how &lt;strong&gt;Copilot Agent Mode&lt;/strong&gt; works! When you prompt Copilot Agent Mode in VS Code to "Add modern rate-limiting to all ASP.NET Core endpoints," it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scans your solution file.&lt;/li&gt;
&lt;li&gt;Identifies all endpoint classes.&lt;/li&gt;
&lt;li&gt;Edits &lt;code&gt;Program.cs&lt;/code&gt; to add middleware.&lt;/li&gt;
&lt;li&gt;Updates individual controller attributes.&lt;/li&gt;
&lt;li&gt;Runs &lt;code&gt;dotnet build&lt;/code&gt; to confirm everything compiles.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Pattern 5: Evaluator Optimizer
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgxj9ourcu7htzblz4yvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgxj9ourcu7htzblz4yvc.png" alt="Evaluator-Optimizer" width="800" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One loop generates the solution, while an evaluation step (like a compiler or unit test suite) provides feedback until the code passes all criteria.&lt;/p&gt;

&lt;p&gt;It matters because LLM make mistakes, but tools like &lt;code&gt;dotnet test&lt;/code&gt; or &lt;code&gt;npm test&lt;/code&gt; provide objective &lt;strong&gt;ground truth&lt;/strong&gt;. Letting Copilot fix its own errors based on compiler output makes it dramatically more accurate!&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Handoffs Between Agents
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why Single Agents Fail
&lt;/h3&gt;

&lt;p&gt;When you try to make one single prompt handle architecture design, database migration, backend coding, and unit testing, you run into &lt;strong&gt;Context Rot&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The prompt becomes huge and expensive.&lt;/li&gt;
&lt;li&gt;The model forgets early instructions.&lt;/li&gt;
&lt;li&gt;The AI gets confused between different roles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Solution:&lt;/strong&gt; Use &lt;strong&gt;Agent Handoffs&lt;/strong&gt;. Divide your system into small, hyper-focused custom agents, and pass the task smoothly from one agent to the next.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd5gyx9m5z4rtpqefng9t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd5gyx9m5z4rtpqefng9t.png" alt="Agent Handoffs" width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Architect to Developer Handoff
&lt;/h3&gt;

&lt;p&gt;In GitHub Copilot, custom agents live inside the &lt;code&gt;.github/agents/&lt;/code&gt; folder as Markdown files with YAML frontmatter.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Define the Architect Agent
&lt;/h4&gt;

&lt;p&gt;Create &lt;code&gt;.github/agents/solution-architect.agent.md&lt;/code&gt;:&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Define the Backend Developer Agent
&lt;/h4&gt;

&lt;p&gt;Create &lt;code&gt;.github/agents/backend-developer.agent.md&lt;/code&gt;:&lt;/p&gt;




&lt;h3&gt;
  
  
  Preserving Context Across Handoffs
&lt;/h3&gt;

&lt;p&gt;When passing work between agents, avoid losing context by using these &lt;strong&gt;Practices&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File-based handoff:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Agent writes output to a shared workspace file (e.g. &lt;code&gt;.copilot/plans/spec.md&lt;/code&gt;) for the next agent to consume.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Structured summary:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Include a short bullet list of key decisions in the handoff prompt.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Minimal tool access:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Grant each agent only the tools it needs (e.g. no terminal access for design agents).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  4. Mastering Agent Skills
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Copilot Customization Pyramid
&lt;/h3&gt;

&lt;p&gt;To turn Copilot into a true expert in your codebase, GitHub provides 5 customization layers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Global Rules&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.github/copilot-instructions.md&lt;/code&gt; / &lt;code&gt;AGENTS.md&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Task Prompts&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.github/prompts/*.prompt.md&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Specialized Personas&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.github/agents/*.agent.md&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Procedural Skills&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.github/skills/*/SKILL.md&lt;/code&gt; (agentskills.io)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;External Tooling&lt;/td&gt;
&lt;td&gt;Model Context Protocol (MCP)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  What is an Agent Skill?
&lt;/h3&gt;

&lt;p&gt;While &lt;strong&gt;Custom Instructions&lt;/strong&gt; tell Copilot &lt;em&gt;what style of code to write&lt;/em&gt;, an &lt;strong&gt;Agent Skill&lt;/strong&gt; teaches Copilot &lt;em&gt;how to perform a specific standard operating procedure (SOP)&lt;/em&gt; step-by-step.&lt;/p&gt;

&lt;p&gt;Agent Skills follow the open &lt;strong&gt;&lt;code&gt;agentskills.io&lt;/code&gt;&lt;/strong&gt; standard, making them portable across AI environments!&lt;/p&gt;




&lt;h3&gt;
  
  
  Integrating External Systems via MCP
&lt;/h3&gt;

&lt;p&gt;To connect your Copilot agents to real-world infrastructure (Azure SQL, GitHub Issues, Jira, Redis), use &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now your agents can directly inspect Azure resource health or query GitHub Issues without leaving VS Code!&lt;/p&gt;




&lt;h3&gt;
  
  
  Human-in-the-Loop Safety &amp;amp; Guardrails
&lt;/h3&gt;

&lt;p&gt;Never leave an autonomous agent completely unsupervised in production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Require Confirmation for Destructive Commands:&lt;/strong&gt; Use terminal execution settings in VS Code to prompt for approval on &lt;code&gt;git push --force&lt;/code&gt;, &lt;code&gt;docker run&lt;/code&gt;, or &lt;code&gt;az deploy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set Iteration Limits:&lt;/strong&gt; Limit Copilot Agent Mode loops to a maximum of 5–10 attempts so it doesn't get stuck in an endless loop if tests fail.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Quick Comparison Matrix
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Configuration Type&lt;/th&gt;
&lt;th&gt;Where It Lives&lt;/th&gt;
&lt;th&gt;Main Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Global Rules&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.github/copilot-instructions.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Coding style, project conventions, library choices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Prompt Files&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.github/prompts/*.prompt.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Single-click reusable task workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom Agents&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.github/agents/*.agent.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Specialized developer personas &amp;amp; handoff rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent Skills&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.github/skills/*/SKILL.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Step-by-step procedure guides (&lt;code&gt;agentskills.io&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MCP Servers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.vscode/mcp.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Real-time external API &amp;amp; database integration&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  6. Conclusion
&lt;/h2&gt;

&lt;p&gt;Building powerful AI agents doesn't require complex external frameworks. By combining &lt;strong&gt;GitHub Copilot Agent Mode&lt;/strong&gt;, &lt;strong&gt;Custom Agents&lt;/strong&gt;, &lt;strong&gt;Agent Skills&lt;/strong&gt;, and &lt;strong&gt;MCP&lt;/strong&gt;, you can build a clean, reliable, and production-grade developer agent right inside your IDE!&lt;/p&gt;

&lt;p&gt;Have you built custom agents or skills for GitHub Copilot yet? Let me know in the comments below!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>dotnet</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>The Context Packet: The Right Architectural Coding Agents</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Mon, 24 Aug 2026 00:44:12 +0000</pubDate>
      <link>https://dev.to/majdizlitni/the-context-packet-the-right-architectural-coding-agents-5agc</link>
      <guid>https://dev.to/majdizlitni/the-context-packet-the-right-architectural-coding-agents-5agc</guid>
      <description>&lt;p&gt;A coding agent with access to your entire repository does not necessarily understand your system better. It may understand less.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3wp87d7x36doh9xupdhi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3wp87d7x36doh9xupdhi.gif" alt="The Odyssey screaming" width="480" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because a large repository may contains obsolete code, and decisions that were never written down. Giving an agent more files increases the amount of text it can inspect, but this does not guarantee it will identify the constraints that matter more.&lt;/p&gt;

&lt;p&gt;The better design is a &lt;strong&gt;context packet&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdm3duz59apykdedxc1sy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdm3duz59apykdedxc1sy.gif" alt="SpongeBob SquarePants Rainbow " width="400" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;a small, versioned, machine-readable description of the system. The packet complements source code by recording the contracts and decisions that source code alone may not reveal.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Repository Access Is Not System Understanding
&lt;/h2&gt;

&lt;p&gt;A normal coding request might look simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Add retry handling to the payment notification worker.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An agent can find the worker, inspect its dependencies, and produce a patch quickly. But a safe implementation depends on questions that may not be answered in the worker's directory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the message delivered at least once?&lt;/li&gt;
&lt;li&gt;Does the payment provider support idempotency keys?&lt;/li&gt;
&lt;li&gt;Which exceptions are transient?&lt;/li&gt;
&lt;li&gt;Does the consumer rely on a specific delivery count?&lt;/li&gt;
&lt;li&gt;Can this change be deployed independently of the producer?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The repository may contain clues, but clues are not contracts.&lt;/p&gt;

&lt;p&gt;When the agent receives only the ticket and nearby files, it fills the gaps with plausible assumptions. When it receives the entire repository, it has a different problem: the important rule may be surrounded by thousands of irrelevant or contradictory signals.&lt;/p&gt;

&lt;p&gt;The gap comes from context design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrieval Boundaries and Signal Density
&lt;/h2&gt;

&lt;p&gt;AI coding systems have a finite context budget. The deeper concern is &lt;strong&gt;signal density&lt;/strong&gt;: the proportion of useful constraints among all the material an agent must interpret.&lt;/p&gt;

&lt;p&gt;Suppose an agent receives 100 files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;10 define the target feature&lt;/li&gt;
&lt;li&gt;20 are related infrastructure&lt;/li&gt;
&lt;li&gt;30 are historical implementations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent can technically read all of them. It still has to decide which rules apply, which code is authoritative, and which behavior is accidental.&lt;/p&gt;

&lt;p&gt;More input creates more opportunities for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conflicting examples&lt;/li&gt;
&lt;li&gt;Outdated implementation patterns&lt;/li&gt;
&lt;li&gt;Incorrect dependency inference&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The common response is to improve the prompt. But prompts are a weak place to store architecture because they are difficult to version and validate.&lt;/p&gt;

&lt;p&gt;The retrieval boundary should answer three questions before content is added to the packet:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Can this change affect it?&lt;/li&gt;
&lt;li&gt;Does it define a contract to keep?&lt;/li&gt;
&lt;li&gt;Is it up to date for this branch/commit/env?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This turns context selection into a policy that can be inspected and improved.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Context Packet Pattern
&lt;/h2&gt;

&lt;p&gt;A context packet is the minimal scoped input for a single change or workflow. It includes only the necessary context and constraints, built from a dependency graph instead of folder structure.&lt;/p&gt;

&lt;p&gt;A useful packet covers these technical layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Intent&lt;/strong&gt;: expected outcome
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boundary&lt;/strong&gt;: services, modules, files, data in scope
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contracts&lt;/strong&gt;: APIs, events, schemas, ownership, compatibility
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraints&lt;/strong&gt;: security, reliability, performance, compliance
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evidence&lt;/strong&gt;: tests, traces, incidents, metrics, examples
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution policy&lt;/strong&gt;: allowed tools and required approvals
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The packet should be versioned and reviewed like code.&lt;br&gt;
It should also remain small enough that an engineer can read it and update it without a separate platform team.&lt;/p&gt;
&lt;h3&gt;
  
  
  A Context Packet in a PR
&lt;/h3&gt;

&lt;p&gt;Taking the example of opening a PR titled &lt;strong&gt;“Retry payment notifications after provider timeouts.”&lt;/strong&gt; The agent does not need a second copy of the repository. It needs the small set of facts that determine whether the change is safe.&lt;/p&gt;

&lt;p&gt;The context assembler follows the changed worker through its dependency graph and produces a short packet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;change&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;retry-payment-notifications&lt;/span&gt;
&lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;payments-platform&lt;/span&gt;

&lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Retry provider timeouts without sending a notification twice.&lt;/span&gt;

&lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PaymentNotificationWorker.cs&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PaymentProviderAdapter.cs&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PaymentNotification.v2.schema.json&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ADR-017-provider-retries.md&lt;/span&gt;

&lt;span class="na"&gt;edit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PaymentNotificationWorker.cs&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;NotificationReplayTests.cs&lt;/span&gt;

&lt;span class="na"&gt;must_preserve&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;NotificationId is stable for every delivery attempt.&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;The adapter classifies provider failures.&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Dead-letter records include the failure classification.&lt;/span&gt;

&lt;span class="na"&gt;checks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;NotificationReplayTests&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DeadLetterContractTests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent makes one scoped change using the packet. It can read/edit code and rerun tests, but not change infra or identity. CI/CD runs two checks and rejects the PR if it edits outside edit or lacks evidence.&lt;/p&gt;

&lt;p&gt;That is the complete loop:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftj3uu2pu2ghtu7h203r9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftj3uu2pu2ghtu7h203r9.png" alt="Complete loop" width="800" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each field has a job:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;read&lt;/code&gt; supplies relevant implementation and architecture decisions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;edit&lt;/code&gt; limits the proposed diff.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;must_preserve&lt;/code&gt; records behavior that source code may not explain.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;checks&lt;/code&gt; connects the packet to the delivery pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep the packet as a change brief, not as a repository summary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context Assembler and Dependency Graph
&lt;/h3&gt;

&lt;p&gt;The assembler starts with the files changed by the pull request and follows declared dependencies outward. A simple graph might look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffdwba2bs0d393survvt3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffdwba2bs0d393survvt3.png" alt="Context Packet Scoop" width="799" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The graph determines what belongs in the packet. A node is included when it is directly changed, is a dependency of a changed node, or defines an operational contract for that dependency. Unrelated services and historical examples stay outside the retrieval boundary.&lt;/p&gt;

&lt;p&gt;The assembler can collect artifacts from controlled sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repository ownership metadata&lt;/li&gt;
&lt;li&gt;Architecture decision records&lt;/li&gt;
&lt;li&gt;API and event schemas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The assembler should rank artifacts by relevance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measuring Packet Value
&lt;/h2&gt;

&lt;p&gt;A well-organized packet is useful only when it improves engineering outcomes.&lt;/p&gt;

&lt;p&gt;Start with four signals:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rework&lt;/td&gt;
&lt;td&gt;Did the agent need repeated corrections about the same constraint?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Boundary violations&lt;/td&gt;
&lt;td&gt;Did the proposal touch files or tools outside its declared scope?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Evidence coverage&lt;/td&gt;
&lt;td&gt;Were the required checks appropriate and actually run?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review effort&lt;/td&gt;
&lt;td&gt;Did reviewers spend less time reconstructing system context?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Tradeoffs and Operational Limits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Context Assembly Has a Maintenance Cost
&lt;/h3&gt;

&lt;p&gt;Owners must update contracts, schemas, and service metadata. This cost is real. It is also preferable to depending on undocumented knowledge that exists only in one engineer's memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Narrow Context Can Hide Important Dependencies
&lt;/h3&gt;

&lt;p&gt;A packet that is too narrow can create false confidence. Include dependency evidence and make the agent able to request an expanded boundary. Expansion should be logged and, for sensitive boundaries, approved.&lt;/p&gt;

&lt;h3&gt;
  
  
  Versioning Adds Friction
&lt;/h3&gt;

&lt;p&gt;Recording packet versions, source revisions, and freshness introduces process overhead. That overhead pays for itself mainly on changes where debugging and rollback are expensive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authorization Belongs to the Runtime
&lt;/h3&gt;

&lt;p&gt;A packet can say that an agent may edit a path, but the runtime must enforce it. Never use a prompt or JSON field as the only security boundary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture Ownership Remains Human
&lt;/h3&gt;

&lt;p&gt;Engineers still define the contract, decide which behavior is intentional, and accept the tradeoffs. The packet makes that work explicit and reusable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The value of a context packet lies in helping an agent distinguish governing rules from code that happens to be nearby.&lt;/p&gt;

&lt;p&gt;AI-assisted development becomes more reliable when context is designed and maintained as part of the engineering system.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>AI Is Changing What 'Correct Software' Means</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Sat, 22 Aug 2026 16:41:58 +0000</pubDate>
      <link>https://dev.to/majdizlitni/ai-is-changing-what-correct-software-means-14hf</link>
      <guid>https://dev.to/majdizlitni/ai-is-changing-what-correct-software-means-14hf</guid>
      <description>&lt;p&gt;Software engineers used to define a "Correct software" via a simple deterministic binary an &lt;em&gt;Expected Output&lt;/em&gt;.&lt;br&gt;
All Test are passed, but this is collapsing, a green CI pipeline no longer guarantees correct software, with AI-generated code that's look syntactically perfect and test-compliant yet they are semantically wrong in a ways that appears in productions.&lt;br&gt;
The bottleneck in software engineering is no longer writing code, it is verifying it execution intent&lt;/p&gt;


&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;The Determinism Illusion&lt;/li&gt;
&lt;li&gt;Why Unit Tests Fail to Catch AI Era Bugs&lt;/li&gt;
&lt;li&gt;The Architecture Shift: From Test Suites to Verification Engines&lt;/li&gt;
&lt;li&gt;Practical Implementation Invariant Verification in Dot NET and Azure&lt;/li&gt;
&lt;li&gt;Tradeoffs and Structural Limitations&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  The Determinism Illusion
&lt;/h2&gt;

&lt;p&gt;Traditional software used to relies on deterministic assertions. We write code with known paths, control inputs, and verify exact results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;CalculateDiscount_StandardUser_ReturnsTenPercent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DiscountCalculator&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetDiscount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Standard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orderTotal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works well because we write the logics and most bugs comes from missed edge cases or small mistakes.&lt;br&gt;
But with AI-generated codes, it follows a patterns based on trained context and user prompt. An agent will write code that pass 100% of our unit tests but silently violation non-functional, implicit system boundaries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It Adds hidden performance costs.&lt;/li&gt;
&lt;li&gt;It breaks state machine idempotency under concurrent execution.&lt;/li&gt;
&lt;li&gt;It bypasses domain entity validation rules by instantiating raw records directly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we got a syntactically valid and test passing code but &lt;strong&gt;architecturally incorrect.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Unit Tests Fail to Catch AI Era Bugs
&lt;/h2&gt;

&lt;p&gt;AI agents are exceptionally good at writing tests for the very code they just generated. If an agent writes a flawed implementation, it generates an equally flawed, matching assertion suite.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd025cmxzesjy0h5wsreh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd025cmxzesjy0h5wsreh.png" alt="AI Generation Loop" width="711" height="950"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When tests mirror the assumptions of the generation engine, unit tests become a confirmation bias machine.&lt;/p&gt;

&lt;p&gt;To govern AI-generated code, we must shift our definition of correctness from &lt;strong&gt;Output Equality&lt;/strong&gt; (&lt;code&gt;Assert.Equal&lt;/code&gt;) to &lt;strong&gt;System Invariants&lt;/strong&gt; (&lt;code&gt;Constraint Validation at Execution Runtime&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture Shift: From Test Suites to Verification Engines
&lt;/h2&gt;

&lt;p&gt;In an AI-native engineering workflow, correctness is defined by &lt;strong&gt;bounded runtime guardrails&lt;/strong&gt; and &lt;strong&gt;architectural fitness functions&lt;/strong&gt;.&lt;br&gt;
Instead of testing whether a function returned &lt;code&gt;10&lt;/code&gt;, a verification engine continuously enforces structural constraints across the entire codebase execution model.&lt;br&gt;
Using this we are not just checking test results we are enforcing rules at runtime and checking that the system design stays valid.&lt;/p&gt;




&lt;h2&gt;
  
  
  Practical Implementation Invariant Verification in Dot NET and Azure
&lt;/h2&gt;

&lt;p&gt;Let's build a practical implementation of an architectural verification pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Enforce System Invariants in the Architecture Pipeline
&lt;/h3&gt;

&lt;p&gt;Instead of trusting AI-generated tests we will enforce rules that our system must always follow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before merge (CI) → check code structure&lt;/li&gt;
&lt;li&gt;At runtime → check what the AI is trying to do
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;NetArchTest.Rules&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Xunit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArchitectureVerificationTests&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;DomainEntities_MustBeImmutable_AndNeverBypassedByAgents&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Enforce that AI-generated code cannot introduce mutable state into the Core Domain&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InCurrentDomain&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ResideInNamespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OrderSystem.Domain"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Should&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BeImmutable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetResult&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;True&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsSuccessful&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"AI generated mutable entities in the domain layer!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Handlers_MustEnforceIdempotencyDecorator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Ensure every generated Command Handler implements IIdempotentCommand&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InCurrentDomain&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;That&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HaveNameEndingWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CommandHandler"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Should&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ImplementInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IIdempotentCommand&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetResult&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;True&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsSuccessful&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"AI generated a command handler lacking explicit idempotency execution!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Runtime Semantic Guardrail Verification Engine
&lt;/h3&gt;

&lt;p&gt;For AI agent workflows running in production or ambient background tasks when it tries to change code or data, we validate its intent before allowing it so we ensure: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No direct DB access outside repositories&lt;/li&gt;
&lt;li&gt;No performance-heavy allocations&lt;/li&gt;
&lt;li&gt;Every external change must trigger an event
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.SemanticKernel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Logging&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;ExecutionIntent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;TaskDescription&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;TargetNamespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ProposedDiff&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;VerificationResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;StructuralDivergenceReason&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgentVerificationEngine&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Kernel&lt;/span&gt; &lt;span class="n"&gt;_kernel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AgentVerificationEngine&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;AgentVerificationEngine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Kernel&lt;/span&gt; &lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AgentVerificationEngine&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_kernel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;VerificationResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;VerifyAgentActionAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ExecutionIntent&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Define hard system invariants that the LLM engine cannot negotiate&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;verificationPrompt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"""
&lt;/span&gt;            &lt;span class="n"&gt;You&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;Architectural&lt;/span&gt; &lt;span class="n"&gt;Verification&lt;/span&gt; &lt;span class="n"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Evaluate&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;proposed&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;against&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;system&lt;/span&gt; &lt;span class="n"&gt;invariants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

            &lt;span class="n"&gt;SYSTEM&lt;/span&gt; &lt;span class="n"&gt;INVARIANTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;direct&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="n"&gt;outside&lt;/span&gt; &lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Repositories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
            &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Memory&lt;/span&gt; &lt;span class="n"&gt;allocations&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;critical&lt;/span&gt; &lt;span class="n"&gt;paths&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;avoid&lt;/span&gt; &lt;span class="n"&gt;heap&lt;/span&gt; &lt;span class="nf"&gt;overhead&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;boxing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;ReadOnlySpan&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;applicable&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
            &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;All&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="n"&gt;modifications&lt;/span&gt; &lt;span class="n"&gt;MUST&lt;/span&gt; &lt;span class="n"&gt;emit&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;IntegrationEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

            &lt;span class="n"&gt;PROPOSED&lt;/span&gt; &lt;span class="n"&gt;CHANGE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;Target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
            &lt;span class="n"&gt;Diff&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;diff&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;

            &lt;span class="n"&gt;Respond&lt;/span&gt; &lt;span class="n"&gt;ONLY&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;JSON&lt;/span&gt; &lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"is_valid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Detailed failure justification"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="s"&gt;""";
&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;KernelArguments&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TargetNamespace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"diff"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProposedDiff&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_kernel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InvokePromptAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verificationPrompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;responseJson&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// System parses verification evaluation deterministically&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deserialize&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;VerificationResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;responseJson&lt;/span&gt;&lt;span class="p"&gt;)!;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Azure Deployment Architecture
&lt;/h3&gt;

&lt;p&gt;Deploy this verification process directly inside your &lt;strong&gt;Azure DevOps Pipeline&lt;/strong&gt; or &lt;strong&gt;GitHub Actions Engine&lt;/strong&gt; alongside Azure Container Apps for isolation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fssj3plhmxlmflsr8n8jt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fssj3plhmxlmflsr8n8jt.png" alt="Azure DevOps Pipeline" width="576" height="1208"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Tradeoffs and Structural Limitations
&lt;/h2&gt;

&lt;p&gt;Moving to an invariant-driven verification architecture introduces real engineering trade-offs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Increased CI Execution Latency&lt;/strong&gt;: Evaluating structural ASTs and executing dynamic LLM-driven verification gates adds 30–90 seconds per pull request compared to simple syntax compilation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Upfront Modeling Cost&lt;/strong&gt;: Defining system invariants requires deep domain expertise. You cannot ask an AI to write your system invariants — doing so reintroduces the confirmation bias loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over-Constrained Evolution&lt;/strong&gt;: Overly strict architectural fitness functions can cause false positives, blocking valid edge-case refactoring tasks generated by agents or human engineers.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;AI is not removing the need for software engineering — &lt;strong&gt;it is raising the level of abstraction.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When writing code becomes frictionless, the primary value of a senior engineer shifts from &lt;em&gt;syntax authoring&lt;/em&gt; to &lt;em&gt;system boundary definition&lt;/em&gt;. Stop relying solely on traditional unit tests to validate AI-generated code. Build verification engines that enforce immutable architecture invariants, audit non-deterministic outputs, and protect runtime stability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Software correctness is no longer about passing unit tests. It is about proving your system cannot violate its core invariants.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;How are you adapting your CI/CD pipelines to handle AI-generated code? Are you relying on static unit testing, or building verification boundaries? Drop your thoughts in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>softwareengineering</category>
      <category>testing</category>
    </item>
    <item>
      <title>Vibium Under the Hood</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Sat, 25 Jul 2026 20:02:58 +0000</pubDate>
      <link>https://dev.to/majdizlitni/vibium-under-the-hood-4k5i</link>
      <guid>https://dev.to/majdizlitni/vibium-under-the-hood-4k5i</guid>
      <description>&lt;p&gt;My &lt;a href="https://dev.to/majdizlitni/vibium-a-cli-browser-automation-tool-3dl9"&gt;previous blog&lt;/a&gt; in my automation series was a first step on how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Vibium&lt;/li&gt;
&lt;li&gt;Record a login scenario&lt;/li&gt;
&lt;li&gt;Visualize recorded test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refreshing, &lt;a href="https://github.com/VibiumDev/vibium" rel="noopener noreferrer"&gt;Vibium is an open source&lt;/a&gt; automation tool, written in Go with JS/TS, Python, and Java client libraries.&lt;/p&gt;

&lt;p&gt;In this blog post, we will go through:&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Protocol Bet: Why WebDriver BiDi&lt;/li&gt;
&lt;li&gt;System Architecture&lt;/li&gt;
&lt;li&gt;Daemon Mode&lt;/li&gt;
&lt;li&gt;Using Vibium MCP and SKILLs&lt;/li&gt;
&lt;li&gt;Reliability vs Speed with AI Agents&lt;/li&gt;
&lt;li&gt;Closing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Protocol Bet: Why WebDriver BiDi
&lt;/h2&gt;

&lt;p&gt;Vibium's design isn't a CLI choice, it's the protocol used underneath.&lt;/p&gt;

&lt;p&gt;Browser automation has gone through three protocol generations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WebDriver (2004–present)&lt;/strong&gt;: Selenium’s foundation. Uses HTTP + JSON with a request/response model that controls browsers in a one-way manner: the browser only responds when asked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chrome DevTools Protocol (2017–present)&lt;/strong&gt;: CDP swapped HTTP for WebSockets, and that unlocked bidirectional communication: the browser sends and receives events in real time like logs, network activity, and DOM changes. Puppeteer and Playwright are both built on CDP, but it is Chrome-internal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WebDriver BiDi (2021–present)&lt;/strong&gt;: The W3C's answer to "what if we kept CDP's bidirectional WebSocket model but made it an actual cross-vendor standard?".&lt;/p&gt;

&lt;p&gt;And that's the main reason I think Vibium is built directly on WebDriver BiDi.&lt;/p&gt;

&lt;p&gt;Below is the diagram presenting these interactions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgrlvfccx1uv5sq7e8xph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgrlvfccx1uv5sq7e8xph.png" alt="Diagram instructions" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here our browser can push events, like messages, and when a page throws an error, &lt;strong&gt;WebDriver BiDi can receive them&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Browser support is still maturing with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chrome/Chromium supports BiDi via ChromeDriver&lt;/li&gt;
&lt;li&gt;Firefox has native support&lt;/li&gt;
&lt;li&gt;Edge inherits Chromium's support&lt;/li&gt;
&lt;li&gt;Safari's support is in development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tooling ecosystem is converging on this protocol, not just Vibium.&lt;/p&gt;

&lt;h2&gt;
  
  
  System Architecture
&lt;/h2&gt;

&lt;p&gt;Vibium ships as a single compiled binary. This indicates that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can invoke it directly from the CLI.&lt;/li&gt;
&lt;li&gt;You can use the MCP server and register it with an agent host.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both surfaces funnel into the same internal command engine, which talks to Chrome over a BiDi WebSocket connection it manages internally.&lt;/p&gt;

&lt;p&gt;Both methods target the Vibium binary, which interacts with Chrome using WebDriver BiDi over WebSocket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9r5tzsr4urs10vezvmjp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9r5tzsr4urs10vezvmjp.png" alt="integrations" width="800" height="792"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two details worth calling out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Vibium uses the same core engine for CLI commands, MCP tools, and language clients. Client libraries connect to the binary through WebSocket instead of rebuilding browser automation logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vibium can be installed as an agent skill via&lt;br&gt;
&lt;code&gt;npx skills add https://github.com/VibiumDev/vibium --skill vibe-check&lt;/code&gt;&lt;br&gt;
allowing AI coding agents to discover and use it through a &lt;code&gt;SKILL.md&lt;/code&gt; definition and automatically resolve the required binary.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Daemon Mode
&lt;/h2&gt;

&lt;p&gt;Daemon mode improves performance. Instead of starting a new browser for every command, it keeps a background browser alive and reuses it across all commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vibium go https://example.com
vibium map
vibium click @e1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the browser starts once, keeping agent workflows faster. The daemon can also be manually controlled with &lt;code&gt;start&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;, and &lt;code&gt;stop&lt;/code&gt; commands, which is useful for CI environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Vibium MCP and SKILLs
&lt;/h2&gt;

&lt;p&gt;Before moving on to the AI integration with Vibium I wanted to clarify the difference between MCP and Skills because there is slight confusion&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;MCP (Model Context Protocol)&lt;/strong&gt; is the runtime used by agents  to execute tools. It controls the communication between agents and binaries.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SKILL.md&lt;/strong&gt; is definition on how to do things it is a file that describes a tool used by MCP
so MCP reads SKILL.md to know how to expose and invoke the skill.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short: MCP execute using skills, and a skill tells MCP how execute.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To use a skill defined via &lt;code&gt;SKILL.md&lt;/code&gt;, you first need to register it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add https://github.com/VibiumDev/vibium &lt;span class="nt"&gt;--skill&lt;/span&gt; vibe-check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc3fu9ezyrvj47mjzq3wb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc3fu9ezyrvj47mjzq3wb.png" alt="using skills" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once added, I used the vibe-check skill to automate a simple scenario.&lt;br&gt;
I use this prompt within GitHub Copilot in agent mode&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use the vibe-Check skill to open https://opensource-demo.orangehrmlive.com/web/index.php/auth/login
and login using:
Username: Admin
Password: admin123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/22GHvcus2Ls"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Reliability vs Speed with AI Agents
&lt;/h2&gt;

&lt;p&gt;Using Vibium with AI is very interesting but this comes with a balance between &lt;strong&gt;speed&lt;/strong&gt; and &lt;strong&gt;reliability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At first glance it seems very fast and smart, it understands what the user wants using simple words and execute actions based on that.&lt;br&gt;
But in practical things can get messy &lt;/p&gt;

&lt;p&gt;It true that AI can know the UI elements with a faster setup but as you can seen a simple login flow still struggles, the agent got stuck and couldn't identify the element from the first attempts.&lt;br&gt;
The interesting part is how it behaves using a quickly recover, &lt;br&gt;
it true that it gives more adaptability but also a less deterministic behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Betting on WebDriver BiDi aligns with a cross-vendor standard for browser automation. Vibium is moving toward a full AI-driven system built on three layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sense (Retina):&lt;/strong&gt; Browser-level observation via a Chrome extension
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Think (Cortex):&lt;/strong&gt; Memory, reasoning, and navigation planning
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Act (Vibium):&lt;/strong&gt; Execution using BiDi
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vibium is early, maturing these layers could move browser automation from "sometimes works" to production-ready.&lt;/p&gt;

&lt;p&gt;Explore the &lt;a href="https://github.com/VibiumDev/vibium/blob/main/skills/vibe-check/SKILL.md" rel="noopener noreferrer"&gt;CLI reference&lt;/a&gt;, &lt;a href="https://github.com/VibiumDev/vibium/blob/main/docs/explanation/webdriver-bidi.md" rel="noopener noreferrer"&gt;BiDi explainer&lt;/a&gt;, and &lt;a href="https://github.com/VibiumDev/vibium/blob/main/ROADMAP.md" rel="noopener noreferrer"&gt;roadmap&lt;/a&gt; in the repo to dig deeper.&lt;/p&gt;




&lt;p&gt;What’s your biggest bottleneck with browser automation today? Drop your thoughts or check out the repo to start experimenting!&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>opensource</category>
      <category>browserautomation</category>
      <category>ai</category>
    </item>
    <item>
      <title>Vibium: A CLI Browser Automation Tool</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Fri, 24 Jul 2026 07:00:00 +0000</pubDate>
      <link>https://dev.to/majdizlitni/vibium-a-cli-browser-automation-tool-3dl9</link>
      <guid>https://dev.to/majdizlitni/vibium-a-cli-browser-automation-tool-3dl9</guid>
      <description>&lt;p&gt;Browser automation has been dominated by tools like &lt;a href="https://www.selenium.dev" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt; and &lt;a href="https://playwright.dev" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;. They're very powerful, but you need to understand the DOM, manage selectors, and set up a testing stack before doing anything meaningful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vibium&lt;/strong&gt; takes a different approach, by using a step-based commands.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open a website&lt;/li&gt;
&lt;li&gt;Find an element&lt;/li&gt;
&lt;li&gt;Fill a field&lt;/li&gt;
&lt;li&gt;Click a button&lt;/li&gt;
&lt;li&gt;Validate the result&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vibium supports two ways for agentic usage:&lt;br&gt;
A command-style skill used for browser automation, and an MCP server for structured workflows. For element discovery, vibium find uses semantic signals like text, labels, placeholders, test IDs, CSS, XPath, and the accessibility tree, then returns stable references that can be reused until the page changes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Why Vibium?&lt;/li&gt;
&lt;li&gt;Installing Vibium&lt;/li&gt;
&lt;li&gt;Your First Vibium Automation&lt;/li&gt;
&lt;li&gt;Understanding the Core Commands&lt;/li&gt;
&lt;li&gt;Recording&lt;/li&gt;
&lt;li&gt;Viewing the Trace&lt;/li&gt;
&lt;li&gt;Where Vibium Fits&lt;/li&gt;
&lt;li&gt;Vibium vs. Selenium vs. Playwright&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Why Vibium?
&lt;/h2&gt;

&lt;p&gt;Traditional automation usually follows a familiar path:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the CSS selector&lt;/li&gt;
&lt;li&gt;Inspect the DOM&lt;/li&gt;
&lt;li&gt;Set up a framework&lt;/li&gt;
&lt;li&gt;Write the code&lt;/li&gt;
&lt;li&gt;Maintain the selectors as the app changes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In Playwright, that ends up looking like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Locator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#username"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;FillAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Admin"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing wrong with that it works, and it's the standard for a reason. But it requires you to already know the DOM structure before you write a single line.&lt;/p&gt;

&lt;p&gt;Vibium flips the workflow around. Instead of hunting for selectors first, you &lt;em&gt;discover&lt;/em&gt; elements interactively and reference them as you go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@e1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Admin"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vibium finds the element for you and hands back a temporary reference (&lt;code&gt;@e1&lt;/code&gt;) that you can immediately act on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Vibium
&lt;/h2&gt;

&lt;p&gt;Install the CLI globally with npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;npm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first browser-based command you run will automatically download a managed &lt;strong&gt;Chrome for Testing&lt;/strong&gt; build, so there's no separate browser setup step.&lt;/p&gt;

&lt;p&gt;Verify everything works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://example.com&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A browser will open with the given URL &lt;/p&gt;

&lt;h2&gt;
  
  
  Your First Vibium Automation
&lt;/h2&gt;

&lt;p&gt;Let's automate a simple login flow against the &lt;a href="https://opensource-demo.orangehrmlive.com" rel="noopener noreferrer"&gt;OrangeHRM demo site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The plan:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start recording&lt;/li&gt;
&lt;li&gt;Open OrangeHRM&lt;/li&gt;
&lt;li&gt;Find the username field and enter a value&lt;/li&gt;
&lt;li&gt;Find the password field and enter a value&lt;/li&gt;
&lt;li&gt;Click the login button&lt;/li&gt;
&lt;li&gt;Stop recording and save the trace&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Using &lt;code&gt;Vibium map&lt;/code&gt; to scans the current page for interactive elements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here a line by line PowerShell script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://opensource-demo.orangehrmlive.com"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@e1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Admin"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@e2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"admin123"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@e3"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1t45beenhw21rlgu12se.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1t45beenhw21rlgu12se.gif" alt="Vibium tutorial" width="720" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's a full, working login automation in about ten lines no selector hunting, no test framework scaffolding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Core Commands
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Start recording&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Open URL&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Find element&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Username"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fill input&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fill&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@e1"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Admin"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Find and click button&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;vibium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@e3"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Recording
&lt;/h2&gt;

&lt;p&gt;This is the one distinction worth internalizing before you build anything real with Vibium.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recording mode&lt;/strong&gt; is great for exploring a workflow, and sketching out an automation quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Viewing the Trace
&lt;/h2&gt;

&lt;p&gt;After you stop recording:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vibium record stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vibium writes out a &lt;code&gt;record.zip&lt;/code&gt; trace file. Open it with the Playwright Trace Viewer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; playwright
playwright show-trace record.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From there you can step through screenshots, actions, timing, failures, and browser state for the whole session handy for debugging a flaky step after the fact.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhmx939jbecw4tf5k9vbb.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhmx939jbecw4tf5k9vbb.gif" alt="playwright record" width="760" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Vibium Fits
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AI agents.&lt;/strong&gt; Vibium's command surface maps naturally onto the kind of steps an LLM already reasons in "open the site, find the login field, enter credentials, click submit, verify the result" which makes it noticeably easier for an agent to generate a working automation than raw locator-based code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test automation.&lt;/strong&gt; Regression suites, smoke tests, end-to-end tests, and user-journey validation (login → create user → update profile → logout, for example) all map cleanly onto Vibium's step-based style.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Internal automation.&lt;/strong&gt; Repetitive browser work data entry, admin dashboards, report pulling, back-office workflows is often not worth building a full test framework for. Vibium's low ceremony makes it a reasonable fit for these one-off or lightly-maintained scripts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vibium vs. Selenium vs. Playwright
&lt;/h2&gt;

&lt;p&gt;Selenium and Playwright still win on ecosystem maturity, plugin support, and battle-tested reliability at scale. Vibium's edge is in how quickly you can go from "I want to automate this" to a working script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Vibium lowers the barrier to entry for browser automation, especially for AI-driven workflows. But it does so by shifting responsibility from the developer to the tool.&lt;/p&gt;

&lt;p&gt;If you're a developer, a QA engineer, or you're building AI agents that need to act on the web, &lt;a href="https://vibium.com" rel="noopener noreferrer"&gt;Vibium&lt;/a&gt; is worth a look.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>testing</category>
      <category>automation</category>
    </item>
    <item>
      <title>What Actually Enforces Code Standards in the AI Era</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Sat, 18 Jul 2026 15:21:09 +0000</pubDate>
      <link>https://dev.to/majdizlitni/what-actually-enforces-code-standards-in-the-ai-era-17kf</link>
      <guid>https://dev.to/majdizlitni/what-actually-enforces-code-standards-in-the-ai-era-17kf</guid>
      <description>&lt;p&gt;If your team has ever spent 20 minutes on a pull request arguing about brace placement instead of the actual bug, welcome to the club.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;StyleCop&lt;/strong&gt; was the tool to keep C# codebases from turning into everyone's personal-style soup. It did its job. But it's also old, slow, and wasn't built for a world where half your codebase might be vibe coded.&lt;/p&gt;

&lt;p&gt;The good news: .NET now ships with everything you need to enforce style natively, faster, and without an extra NuGet package. This post walks through &lt;em&gt;why&lt;/em&gt; the old approach creaks under modern workloads, and gives you a copy-pasteable migration plan to fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Real Cost of Style Debates&lt;/li&gt;
&lt;li&gt;Quick Refresher: What Is StyleCop?&lt;/li&gt;
&lt;li&gt;Do We Even Need Linters Now That AI Writes Code?&lt;/li&gt;
&lt;li&gt;The Problem With StyleCop: It's Slow&lt;/li&gt;
&lt;li&gt;The Modern Toolbox&lt;/li&gt;
&lt;li&gt;The 3 Layer Guardrail Strategy&lt;/li&gt;
&lt;li&gt;Step by Step Migration Guide&lt;/li&gt;
&lt;li&gt;Before and After Seeing It In Action&lt;/li&gt;
&lt;li&gt;Key Takeaways&lt;/li&gt;
&lt;li&gt;Wrapping Up&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Real Cost of Style Debates
&lt;/h2&gt;

&lt;p&gt;Nobody has ever gotten a promotion for winning a tabs-vs-spaces argument. Yet these debates eat real time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PR bikeshedding&lt;/strong&gt;,reviewers nitpick spacing instead of catching actual logic bugs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Noisy git diffs&lt;/strong&gt;,one developer's auto-formatter touches 300 lines to fix a 3-line bug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cognitive overhead&lt;/strong&gt;,jumping between services that each "feel" different slows everyone down.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A linter's whole job is to make these arguments boring and automatic, so humans can focus on things that actually matter,like whether the code &lt;em&gt;works&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Refresher: What Is StyleCop?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;StyleCop&lt;/strong&gt; (and its Roslyn-based version, &lt;code&gt;StyleCop.Analyzers&lt;/code&gt;) is a static analysis tool that checks the &lt;em&gt;visual grammar&lt;/em&gt; of your C# code,not bugs, not security holes, just style:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are public members documented?&lt;/li&gt;
&lt;li&gt;Are namespaces organized consistently?&lt;/li&gt;
&lt;li&gt;Do braces follow the "approved" pattern?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's not checking if your code is &lt;em&gt;correct&lt;/em&gt;. It's checking if your code &lt;em&gt;looks&lt;/em&gt; correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do We Even Need Linters Now That AI Writes Code?
&lt;/h2&gt;

&lt;p&gt;Short answer: &lt;strong&gt;yes, more than ever.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI coding assistants (Copilot, Cursor, and friends) are great at logic, but they have zero awareness of your team's conventions. They're trained on millions of repos with wildly different styles, so pasted-in AI code tends to bring some chaos with it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Paradigm mixing&lt;/strong&gt;,old-school patterns sitting right next to brand-new C# syntax in the same file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Random formatting&lt;/strong&gt;,inconsistent spacing and bracing, because the model has no idea what &lt;em&gt;your&lt;/em&gt; team prefers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comment bloat&lt;/strong&gt;,giant XML doc comments explaining that &lt;code&gt;GetName()&lt;/code&gt; "gets the name."&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Tip:&lt;/strong&gt; Think of AI-generated code like a very talented intern who's never seen your style guide. Brilliant ideas, questionable formatting. It needs a quick pass before it joins the team.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Problem With StyleCop: It's Slow
&lt;/h2&gt;

&lt;p&gt;Here's the part that actually hurts: &lt;code&gt;StyleCop.Analyzers&lt;/code&gt; walks the compiler's entire Abstract Syntax Tree (AST) &lt;em&gt;every time you build locally&lt;/em&gt;. On a large, modern codebase, that adds real, measurable time to every single compile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Code → Hit Build → Roslyn AST + Heavy StyleCop Analysis → Slow Build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it gets worse: hundreds of style rules are configured as &lt;strong&gt;Warnings&lt;/strong&gt;, so your build output turns into a wall of noise. Real errors get buried underneath "add a blank line here" messages. That's not code quality,that's warning fatigue.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Modern Toolbox
&lt;/h2&gt;

&lt;p&gt;Microsoft baked style enforcement directly into the .NET SDK, so you don't need a heavyweight third-party package anymore. Here are your main options:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Native &lt;code&gt;.editorconfig&lt;/code&gt; (the real successor to StyleCop)&lt;/strong&gt;&lt;br&gt;
Define your rules in a plain text file. The .NET SDK reads it instantly and surfaces issues as built-in compiler diagnostics. No extra packages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. CSharpier&lt;/strong&gt;&lt;br&gt;
An opinionated formatter, like Prettier for C#. It skips debates entirely,one deterministic output, no configuration arguments. Runs outside the compiler, so it doesn't touch build performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. SonarQube / SonarCloud&lt;/strong&gt;&lt;br&gt;
For the &lt;em&gt;deep&lt;/em&gt; stuff,security holes, memory leaks, async anti-patterns,push that to a cloud-based SAST engine instead of your local build. Keep local checks fast and lightweight; let the cloud do the heavy lifting asynchronously.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Good for&lt;/th&gt;
&lt;th&gt;Runs where&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;.editorconfig&lt;/code&gt; + SDK analyzers&lt;/td&gt;
&lt;td&gt;Style, naming, layout&lt;/td&gt;
&lt;td&gt;Local build (fast)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSharpier&lt;/td&gt;
&lt;td&gt;Deterministic formatting&lt;/td&gt;
&lt;td&gt;Out-of-process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SonarQube/Cloud&lt;/td&gt;
&lt;td&gt;Security &amp;amp; deep quality checks&lt;/td&gt;
&lt;td&gt;CI / cloud (async)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  The 3 Layer Guardrail Strategy
&lt;/h2&gt;

&lt;p&gt;The trick to using AI tools without letting them wreck your codebase is a simple pipeline: &lt;strong&gt;Seed → Ground → Enforce.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. SEED                 2. GROUND              3. ENFORCE
AI Instruction File  →  IDE Format on Save  →  CI Gate
(AGENTS.md)             (.editorconfig)        (dotnet format)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seed&lt;/strong&gt;: Tell the AI your conventions upfront, before it generates a single line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ground&lt;/strong&gt;: Let your IDE auto-fix formatting the moment code is pasted or saved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enforce&lt;/strong&gt;: Fail the build in CI if anything slipped through ungrounded.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three checkpoints. Nothing style-broken survives all three.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step by Step Migration Guide
&lt;/h2&gt;

&lt;p&gt;Here's the hands-on plan to move off StyleCop and onto native tooling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Set Project-Wide Standards
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;Directory.Build.props&lt;/code&gt; file at the root of your repo (next to your &lt;code&gt;.sln&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Project&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Turn on the SDK's built-in Roslyn analyzers --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;EnableNETAnalyzers&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/EnableNETAnalyzers&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;AnalysisLevel&amp;gt;&lt;/span&gt;latest&lt;span class="nt"&gt;&amp;lt;/AnalysisLevel&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;AnalysisMode&amp;gt;&lt;/span&gt;Recommended&lt;span class="nt"&gt;&amp;lt;/AnalysisMode&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Make the build actually respect .editorconfig --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;EnforceCodeStyleInBuild&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/EnforceCodeStyleInBuild&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This applies the same rules across every project in the solution, no more "well, &lt;em&gt;my&lt;/em&gt; microservice does it differently."&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Generate Your &lt;code&gt;.editorconfig&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new editorconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then customize it. Here's a solid starting template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="py"&gt;root&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;

&lt;span class="nn"&gt;[*.cs]&lt;/span&gt;
&lt;span class="c"&gt;# Indentation &amp;amp; layout
&lt;/span&gt;&lt;span class="py"&gt;indent_style&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;space&lt;/span&gt;
&lt;span class="py"&gt;indent_size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;4&lt;/span&gt;
&lt;span class="py"&gt;end_of_line&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;lf&lt;/span&gt;
&lt;span class="py"&gt;insert_final_newline&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true&lt;/span&gt;

&lt;span class="c"&gt;# Modern C# preferences
&lt;/span&gt;&lt;span class="py"&gt;csharp_style_file_scoped_namespaces&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;true:error&lt;/span&gt;

&lt;span class="c"&gt;# Explicit rule mappings (these replace old StyleCop rules)
&lt;/span&gt;&lt;span class="py"&gt;dotnet_diagnostic.IDE0005.severity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;warning   # remove unused usings&lt;/span&gt;
&lt;span class="py"&gt;dotnet_diagnostic.IDE0040.severity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;warning   # require explicit access modifiers&lt;/span&gt;
&lt;span class="py"&gt;dotnet_diagnostic.IDE0055.severity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;warning   # flag whitespace/brace issues&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Give Your AI Tools the Memo
&lt;/h3&gt;

&lt;p&gt;Drop a &lt;code&gt;AGENTS.md&lt;/code&gt; file in your repo root so AI assistants know the rules &lt;em&gt;before&lt;/em&gt; they start typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# C# Code Generation Rules&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; All generated code must follow the root &lt;span class="sb"&gt;`.editorconfig`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Use file-scoped namespaces only.
&lt;span class="p"&gt;-&lt;/span&gt; Keep classes tightly encapsulated; prefer primary constructors.
&lt;span class="p"&gt;-&lt;/span&gt; Skip self-explanatory XML doc comments on basic properties.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the "Seed" layer from earlier; cheap insurance against a lot of cleanup later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Automate Formatting Locally
&lt;/h3&gt;

&lt;p&gt;In your IDE (Visual Studio, VS Code, Rider,doesn't matter which), turn on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Format on Save&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Format on Paste&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what actually "grounds" AI-pasted code into your team's style, automatically, with zero manual effort.&lt;/p&gt;

&lt;p&gt;Need to clean up an entire existing codebase in one go?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Add a CI Gate
&lt;/h3&gt;

&lt;p&gt;Add this to your pipeline (GitHub Actions, Azure DevOps, whatever you use) &lt;em&gt;before&lt;/em&gt; the build step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Verify Code Style &amp;amp; Layout Compliance&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet format --verify-no-changes --verbosity normal&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Execute Production Build&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet build --configuration Release&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If anyone bypasses their IDE formatting (we all know someone), the pipeline catches it before it merges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before and After Seeing It In Action
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt;: technically compiles, but it's a mess:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// InconsistentOrderProcessingService.cs&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;MyApp.Core&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyApp.Services&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;orderService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IRepository&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;orderService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IRepository&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;

      &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;==&lt;/span&gt;&lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Order context is missing."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Business execution path...&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt;,run &lt;code&gt;dotnet format&lt;/code&gt;, and this is what comes out the other side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// OrderProcessingService.cs&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;MyApp.Core&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyApp.Services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderProcessingService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IRepository&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;OrderProcessingService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentNullException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ProcessOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InvalidOperationException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Order with ID &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; was not found."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Business execution path...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same logic. Zero manual cleanup. Nobody had to open a PR comment thread about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;StyleCop is slow&lt;/strong&gt; because it walks the full AST on every local build; that adds up fast on large codebases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-generated code needs grounding&lt;/strong&gt;, not banning. Seed it with conventions, then auto-format on save.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.editorconfig&lt;/code&gt; + SDK analyzers&lt;/strong&gt; replace most of what StyleCop did, natively, and faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI should verify, not fix.&lt;/strong&gt; Use &lt;code&gt;dotnet format --verify-no-changes&lt;/code&gt; as a gate, not a cleanup crew.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split concerns&lt;/strong&gt;: style stays local and fast; deep security/quality checks (SonarQube) move to CI/cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ready to use template
&lt;/h2&gt;

&lt;p&gt;Reading about code standards is easy. Applying them consistently across a team is the hard part.&lt;/p&gt;

&lt;p&gt;To make this process easier, I created a ready-to-use .NET code governance template that packages the approach described in this article&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://github.com/Majdi-Zlitni/DotStyle" rel="noopener noreferrer"&gt;DotStyle .NET Code Governance Template&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Moving off StyleCop isn't about lowering your standards, it's about enforcing them somewhere that doesn't slow you down. Seed your AI tools with clear rules, let your IDE ground the output automatically, and use CI as the final backstop. Fast local builds, clean diffs, and PR reviews that actually talk about the code instead of the commas.&lt;/p&gt;

&lt;p&gt;Give it a try on one repo this week, use a proper &lt;code&gt;.editorconfig&lt;/code&gt;, wire up &lt;code&gt;dotnet format&lt;/code&gt; in CI, and see how much quieter your next pull request review is.&lt;/p&gt;

&lt;p&gt;Have a different setup that works for your team? something else entirely? Drop it in the comments 👇&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Bypassing the Parser: Connecting Azure AI Foundry to VS Code Copilot via BYOK</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Wed, 17 Jun 2026 09:51:35 +0000</pubDate>
      <link>https://dev.to/majdizlitni/bypassing-the-parser-connecting-azure-ai-foundry-to-vs-code-copilot-via-byok-35d</link>
      <guid>https://dev.to/majdizlitni/bypassing-the-parser-connecting-azure-ai-foundry-to-vs-code-copilot-via-byok-35d</guid>
      <description>&lt;p&gt;The &lt;strong&gt;vibe coding&lt;/strong&gt; era just took a massive hit. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbbi5fzdce38gf5j9b1b9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbbi5fzdce38gf5j9b1b9.gif" alt="frightening" width="399" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As of &lt;strong&gt;June 1, 2026&lt;/strong&gt;, GitHub completely dismantled its old request-based model for Copilot and transitioned to a strict Usage-Based Billing Model powered by &lt;a href="https://docs.github.com/en/copilot/concepts/billing/usage-based-billing-for-individuals" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub AI Credits&lt;/strong&gt;&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;For developers riding on the &lt;a href="https://docs.github.com/en/copilot/how-tos/copilot-on-github/set-up-copilot/enable-copilot/set-up-for-students" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub Copilot Student plan&lt;/strong&gt;&lt;/a&gt;, the reality is harsh: while basic inline code completions remain unlimited, Copilot Chat and agentic features are now heavily restricted. To make matters worse, top-tier reasoning models have been completely stripped from the Student tier self-selection menu to keep the free tier sustainable.&lt;/p&gt;

&lt;p&gt;But if you are a student with an &lt;a href="https://azure.microsoft.com/en-us/free/students" rel="noopener noreferrer"&gt;&lt;strong&gt;Azure for Students subscription&lt;/strong&gt;&lt;/a&gt;, you hold a massive golden ticket in your hands: &lt;strong&gt;Free Azure cloud credits&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykirqicdl6xklhfmjcef.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykirqicdl6xklhfmjcef.gif" alt="Money moeny" width="437" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By using the &lt;strong&gt;Bring Your Own Key (BYOK)&lt;/strong&gt; feature inside VS Code, you can deploy cutting-edge coding models on your own Azure instance and route them straight into your IDE, falling into three distinct tiers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud-Hosted Enterprise Models (Azure AI Foundry &amp;amp; OpenAI)&lt;/li&gt;
&lt;li&gt;External Third-Party API Gateways (DeepSeek, OpenRouter &amp;amp; Anthropic)&lt;/li&gt;
&lt;li&gt;Fully Offline Local Models (Ollama, vLLM &amp;amp; Foundry Local)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While BYOK supports everything from local Ollama instances to third-party gateways, this guide will focus specifically on Azure subscription credits using Azure AI Foundry.&lt;/p&gt;

&lt;p&gt;Here is how to trick the system, bypass the budget limits, and build your own autonomous development environment.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fww72z5wq55j5ccxyglfx.gif" alt="haking" width="480" height="270"&gt;
&lt;/h2&gt;
&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites: Snagging Your Azure Student Subscription&lt;/li&gt;
&lt;li&gt;
vs code Configuration Blueprint

&lt;ul&gt;
&lt;li&gt;Step 1: Open the Custom Models Panel&lt;/li&gt;
&lt;li&gt;Step 2: Input Your Azure Endpoint Details&lt;/li&gt;
&lt;li&gt;Step 3: Clear the IDE Cache Layers&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The Result: Infinite Coding Freedom&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Prerequisites: Snagging Your Azure Student Subscription
&lt;/h2&gt;

&lt;p&gt;First you need a valid &lt;strong&gt;Azure subscription&lt;/strong&gt; with active credits to host your models. If you don't have one yet, Microsoft offers a dedicated &lt;strong&gt;Azure for Students&lt;/strong&gt; tier that gives you free cloud credits annually with no credit card required.&lt;/p&gt;
&lt;h3&gt;
  
  
  Scenario A: You Already Have an Active Azure subscription
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Log into &lt;a href="https://ai.azure.com/home" rel="noopener noreferrer"&gt;Azure AI Foundry&lt;/a&gt; and create a new Azure Foundry resource.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8169gnnusme2iikj5seq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8169gnnusme2iikj5seq.png" alt="Microsoft Foundry resource" width="630" height="490"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new project under your subscription(student subscription if you have one). Select an optimal region for model availability (for my case I selected &lt;code&gt;Sweden Central&lt;/code&gt;). Create your resource group.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw23mlmlt49hc4crg8ztw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw23mlmlt49hc4crg8ztw.png" alt="New foundry project" width="624" height="663"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Navigate to the &lt;strong&gt;Model Catalog&lt;/strong&gt; and choose &lt;strong&gt;Explore Models&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F68n70p9dq05fjx29kgg8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F68n70p9dq05fjx29kgg8.png" alt="Explore model" width="800" height="85"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select your preferred available coding model.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fenwvfnudelwck6jrz1r4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fenwvfnudelwck6jrz1r4.png" alt="Model selection" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy it using the default settings, making note of the target model name (e.g.,for my case I used &lt;code&gt;gpt-5.3-codex&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy your &lt;strong&gt;Endpoint URL&lt;/strong&gt; and &lt;strong&gt;API Keys&lt;/strong&gt; from the model deployment dashboard. Keep these secure we will need them for VS Code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Scenario B: You Need to Create One
&lt;/h3&gt;

&lt;p&gt;Head over to the official &lt;a href="https://azure.microsoft.com/en-us/free/students" rel="noopener noreferrer"&gt;Azure for Students Portal&lt;/a&gt;, sign in using your academic university email address (&lt;code&gt;.edu&lt;/code&gt; or your institutional domain), and verify your student status. Your cloud sandbox and free credit allotment will provision instantly.&lt;/p&gt;


&lt;h2&gt;
  
  
  vs code Configuration Blueprint
&lt;/h2&gt;

&lt;p&gt;Instead of wrestling with native extension limitations, we are going to configure your connection as an open-standard, &lt;strong&gt;OpenAI-Compatible gateway&lt;/strong&gt;, while preserving the specialized &lt;strong&gt;Responses API&lt;/strong&gt; handling required by modern Azure Foundry endpoints.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Open the Custom Models Panel
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Launch &lt;strong&gt;VS Code&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Open your &lt;strong&gt;Copilot Chat&lt;/strong&gt; panel on the sidebar.&lt;/li&gt;
&lt;li&gt;Click on the model selection dropdown menu at the top or bottom of the chat interface.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;"Other Models..."&lt;/strong&gt; from the bottom of the list.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuj2ktitlhj5g2p735jk4.png" alt="other models option" width="391" height="255"&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Step 2: Input Your Azure Endpoint Details
&lt;/h3&gt;

&lt;p&gt;A new UI panel labeled &lt;strong&gt;"Adding custom endpoint"&lt;/strong&gt; will appear. Populate the fields using the credentials you copied from your Azure AI Foundry dashboard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Endpoint URL:&lt;/strong&gt; Paste your Azure endpoint (ensure it targets the base &lt;code&gt;/openai/v1&lt;/code&gt; route).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Key:&lt;/strong&gt; Paste your secure Azure endpoint key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model ID:&lt;/strong&gt; Match it to your deployment name (e.g., &lt;code&gt;gpt-5.3-codex&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6l7rqc8ab4xr78s2dy3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6l7rqc8ab4xr78s2dy3.png" alt="custom endpoint" width="799" height="439"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  💡 Pro-Tip: Deep Tweaking via JSON
&lt;/h3&gt;

&lt;p&gt;If you prefer fine-grained control or want to explicitly enforce parameters like context windows or vision support, you can open your user &lt;code&gt;chatLanguageModels.json&lt;/code&gt; file via the Command Palette (&lt;code&gt;Ctrl+Shift+P&lt;/code&gt; / &lt;code&gt;Cmd+Shift+P&lt;/code&gt; -&amp;gt; &lt;strong&gt;&lt;code&gt;Chat: Manage Language Models&lt;/code&gt;&lt;/strong&gt;) and drop in this clean schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[Azure AI Foundry (BYOK)]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"vendor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"customendpoint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"apiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${input:chat.lm.secret.YOUR_SECRET_ID}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"apiType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"responses"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"models"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gpt-5.3-codex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GPT-5.3 Codex (Foundry)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[https://***.services.ai.azure.com/openai/v1](https://***.services.ai.azure.com/openai/v1)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"toolCalling"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"vision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"maxInputTokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;128000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"maxOutputTokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Clear the IDE Cache Layers
&lt;/h3&gt;

&lt;p&gt;To ensure VS Code registers the new custom endpoint layout:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reload your window via the Command Palette (&lt;code&gt;Developer: Reload Window&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Open your Copilot Chat panel.&lt;/li&gt;
&lt;li&gt;Click the model dropdown selection menu. You should now see your deployed model available as a selectable model option!
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb6zprj8o7e21xclptl2w.png" alt="your model" width="380" height="258"&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Result: Infinite Coding Freedom
&lt;/h2&gt;

&lt;p&gt;Once your endpoint is active and your environment is refreshed, you are ready to build without constraints. &lt;/p&gt;

&lt;p&gt;You have officially decoupled your IDE's intelligence layer from restrictive credit pools. By routing your Azure subscription credits straight into your workspace via a BYOK configuration, you gain full autonomy over your development ecosystem completely free of token caps or artificial feature tiers. Happy hacking!&lt;/p&gt;

&lt;p&gt;I would love to get your feedback and insights on this.&lt;/p&gt;

&lt;p&gt;Are you currently implementing BYOK setups or custom routing within your local teams and IDEs?&lt;br&gt;
How are you balancing API performance and cost management across modern developer environments?&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>githubcopilot</category>
      <category>azure</category>
    </item>
    <item>
      <title>Stop Writing 'Fixed Bug': Git Day-to-Day with Conventional Commits</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Fri, 15 May 2026 15:12:57 +0000</pubDate>
      <link>https://dev.to/majdizlitni/stop-writing-fixed-bug-git-day-to-day-with-conventional-commits-44ol</link>
      <guid>https://dev.to/majdizlitni/stop-writing-fixed-bug-git-day-to-day-with-conventional-commits-44ol</guid>
      <description>&lt;p&gt;We’ve all been there. A critical bug is reported in production. You grab your coffee, crack your knuckles, and run 'git log' to trace when the issue was introduced. And what do you see?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;7a3b4c9 fixed bug
1d9e2f4 updated config
9f8a7b6 wip
3c2d1e8 finally works pls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1r5qroj4fyizyhg8wo32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1r5qroj4fyizyhg8wo32.png" alt="A chaotic commit history compared side-by-side with a perfectly clean, structured Conventional Commit history" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tracking what actually happened turns into an archaeological dig. When hundreds of developers on a team all push commits with vague messages, your repository's history becomes a chaotic nightmare.&lt;/p&gt;

&lt;p&gt;But there is a better way. Welcome to &lt;strong&gt;Conventional Commits&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a Conventional Commit?
&lt;/h2&gt;

&lt;p&gt;A &lt;a href="https://www.conventionalcommits.org/" rel="noopener noreferrer"&gt;Conventional Commit&lt;/a&gt; provides a lightweight, standardized structure to your commit messages. By imposing a simple set of rules, commits become easily readable by both human developers and automated machines (like your CI/CD pipelines).&lt;/p&gt;

&lt;p&gt;Think of it as turning your Git history from a messy journal into a structured database.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Anatomy of a Perfect Commit
&lt;/h3&gt;

&lt;p&gt;The standard format is simple but powerful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;[optional scope]: &amp;lt;description&amp;gt;

[optional body]

[optional footer(s)] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a real-world comparison:&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Bad Commit&lt;/strong&gt;: 'fixed the token issue'&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Good Commit&lt;/strong&gt;: 'fix(auth): resolve token parsing issue caused by expired JWT format'&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Commit Types (Prefixes)
&lt;/h3&gt;

&lt;p&gt;To keep things consistent, we use predefined prefixes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;feat:&lt;/strong&gt; A new feature for the user or the API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;fix:&lt;/strong&gt; A bug fix for the user or the API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;docs:&lt;/strong&gt; Documentation-only changes (README, swagger, etc.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;style:&lt;/strong&gt; Formatting, missing semi-colons, etc; no code change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;chore:&lt;/strong&gt; Changes to the build process or auxiliary tools (e.g., updating dependencies).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;refactor:&lt;/strong&gt; A code change that neither fixes a bug nor adds a feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;test:&lt;/strong&gt; Adding missing tests or refactoring tests; no production code change.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Pro Tip:&lt;/strong&gt; Need to memorize these? Add a '.gitmessage' template to your project so every time you run 'git commit', the types are printed as comments in your editor!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔄 Revamping Your Daily Git Workflow
&lt;/h2&gt;

&lt;p&gt;Adopting Conventional Commits is more than just typing a prefix; it’s a mindset shift. Your daily workflow adjusts to prioritize clean, isolated history.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Branch Out
&lt;/h3&gt;

&lt;p&gt;Always ensure you're starting on a clean, isolated branch from 'main'.&lt;br&gt;
&lt;code&gt;bash&lt;br&gt;
git checkout main&lt;br&gt;
git pull&lt;br&gt;
git checkout -b feature/user-profile&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Make Isolated Changes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pitfall:&lt;/strong&gt; Don't group unrelated changes together. If you are fixing a UI bug and adding a new database field, those belong in &lt;em&gt;separate&lt;/em&gt; commits, and possibly separate branches. Keep your commits atomic.&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Commit Accurately
&lt;/h3&gt;

&lt;p&gt;Use the prefixes rigorously! Be descriptive but concise.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add src/components/UserProfile.tsx
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat(ui): add user profile dashboard component"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Rebase, Don't Merge (Usually)
&lt;/h3&gt;

&lt;p&gt;When bringing your feature branch up to date with 'main', prefer rebasing over merging.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Merging&lt;/strong&gt; ('git merge main') creates a "merge commit," tying two histories together. It's safe, but it makes the history look like a tangled web.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rebasing&lt;/strong&gt; ('git rebase main') plucks your commits and plays them &lt;em&gt;on top&lt;/em&gt; of the latest 'main'. It creates a beautiful, perfectly linear history.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ataqi1uqhqw3ihlghec.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ataqi1uqhqw3ihlghec.png" alt="A diagram illustrating tracking isolated changes on a feature branch, followed by a rebase against main" width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch origin
&lt;span class="c"&gt;# Rebase your current branch onto the latest main&lt;/span&gt;
git rebase origin/main
&lt;span class="c"&gt;# Resolve any conflicts, then force push safely:&lt;/span&gt;
git push &lt;span class="nt"&gt;--force-with-lease&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why Go Through the Trouble?
&lt;/h2&gt;

&lt;p&gt;Making your commits structured feels like extra typing at first. But the ROI is massive:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Instant Context for Reviewers:&lt;/strong&gt; Your peers instantly understand the scope and intent of your Pull Request. 'chore(deps)' tells them this is a dependency update, while 'feat(checkout)' tells them to look for new business logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Changelogs:&lt;/strong&gt; Scripts can automatically parse 'feat' and 'fix' commits to generate pristine Release Notes instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD Magic:&lt;/strong&gt; Tools like Semantic Release rely wholly on these prefixes to automate versioning and deployments (which we cover in the next article!).&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Conclusion &amp;amp; Next Steps
&lt;/h2&gt;

&lt;p&gt;Switching to Conventional Commits transforms how your team interacts with the codebase. You stop guessing what a commit does and start treating your Git history as a source of truth.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your Challenge for Today:&lt;/strong&gt;&lt;br&gt;
Try formatting your next 3 commits using the Conventional format. See how much cleaner your 'git log' looks!&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Part 2&lt;/strong&gt; of this series, we will take this to the next level. We'll show you how to leverage these structured commits to &lt;em&gt;completely automate your application versioning&lt;/em&gt; using &lt;strong&gt;Semantic Release&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you found this helpful, drop a ❤️ below! How does your team structure commit messages? Let me know in the comments!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Level Up Your Dev Setup: Get GitHub Copilot for Free with the Student Developer Pack</title>
      <dc:creator>Majdi Zlitni</dc:creator>
      <pubDate>Wed, 22 Apr 2026 10:54:24 +0000</pubDate>
      <link>https://dev.to/majdizlitni/level-up-your-dev-setup-get-github-copilot-for-free-with-the-student-developer-pack-20m4</link>
      <guid>https://dev.to/majdizlitni/level-up-your-dev-setup-get-github-copilot-for-free-with-the-student-developer-pack-20m4</guid>
      <description>&lt;p&gt;Hey coding wizards, open source heroes, and dedicated learners! Ever felt like the tools you need to build the next big thing are locked behind a paywall steeper than mount Everest? Or maybe you're just tired of writing boilerplate code manually while your wallet looks a bit thin?&lt;/p&gt;

&lt;p&gt;Fear not! &lt;a href="https://github.com" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/a&gt;, in its infinite wisdom and generosity, has compiled the ultimate cheat code for students: the &lt;a href="https://education.github.com/pack" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub Student Developer Pack&lt;/strong&gt;&lt;/a&gt;. But what exactly is it, how do you get your hands on it, and most importantly, how can you use it to access top-tier AI tools like &lt;a href="https://github.com/copilot" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt;&lt;/a&gt;? Let's dive in!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnda5uweqz7cmhbf42lv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnda5uweqz7cmhbf42lv.gif" alt="faster typer" width="500" height="300"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What is the Developer Pack?&lt;/li&gt;
&lt;li&gt;How to Claim Your Pack: Step by Step&lt;/li&gt;
&lt;li&gt;The Ultimate AI Workbench: VS Code and GitHub Copilot&lt;/li&gt;
&lt;li&gt;Tips to Maximize Your Pack&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  What is the Developer Pack?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://education.github.com/pack" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub Student Developer Pack&lt;/strong&gt;&lt;/a&gt; provides students with free access valid for 2 years to premium developer tools, cloud hosting, domains, and learning platforms to kickstart your career.&lt;br&gt;
After the 2-year period, you can reapply and renew your benefits&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who Qualifies?&lt;/strong&gt;&lt;br&gt;
Any currently enrolled &lt;a href="https://education.github.com/pack/join" rel="noopener noreferrer"&gt;student&lt;/a&gt; (high school, college, university, or verified bootcamps) aged 13+ with a verifiable school email address or proof of enrollment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Included?&lt;/strong&gt; You get a massive bundle of resources, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GitHub Ecosystem&lt;/strong&gt;: Free &lt;a href="https://docs.github.com/en/get-started/learning-about-github/githubs-plans#github-pro" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub Pro&lt;/strong&gt;&lt;/a&gt; &amp;amp; &lt;a href="//github.com/copilot"&gt;&lt;strong&gt;GitHub Copilot&lt;/strong&gt;&lt;/a&gt;. Includes 1 free certification voucher.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://azure.microsoft.com/en-us" rel="noopener noreferrer"&gt;&lt;strong&gt;Microsoft Azure&lt;/strong&gt;&lt;/a&gt;: $100 credit and 25+ free services for 1 year.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cloud &amp;amp; Domains&lt;/strong&gt;: $200 &lt;a href="https://www.digitalocean.com" rel="noopener noreferrer"&gt;&lt;strong&gt;DigitalOcean&lt;/strong&gt;&lt;/a&gt; credit. Grab a free &lt;code&gt;.me&lt;/code&gt; (w/ SSL) from &lt;a href="https://www.namecheap.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Namecheap&lt;/strong&gt;&lt;/a&gt;, a &lt;code&gt;.TECH&lt;/code&gt; domain, or choose from 25+ other extensions like &lt;code&gt;.live&lt;/code&gt; and &lt;code&gt;.dev&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developer Tools&lt;/strong&gt;: Full educational license for all &lt;a href="https://www.jetbrains.com/academy/student-pack/" rel="noopener noreferrer"&gt;&lt;strong&gt;JetBrains&lt;/strong&gt;&lt;/a&gt; IDEs (IntelliJ, PyCharm, etc.), plus a &lt;a href="https://www.datadoghq.com/blog/datadog-github-student-developer-pack/" rel="noopener noreferrer"&gt;&lt;strong&gt;Datadog&lt;/strong&gt;&lt;/a&gt; Pro Account (10 servers for 2 years).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learning &amp;amp; Interview Prep&lt;/strong&gt;: 3 months of &lt;a href="https://campus.datacamp.com" rel="noopener noreferrer"&gt;&lt;strong&gt;DataCamp&lt;/strong&gt;&lt;/a&gt;, free &lt;a href="https://www.pluralsight.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Pluralsight&lt;/strong&gt;&lt;/a&gt; training, 1 week of &lt;a href="https://www.interviewcake.com/github-students" rel="noopener noreferrer"&gt;&lt;strong&gt;Interview cake&lt;/strong&gt;&lt;/a&gt;, and 20 free questions + 10% off at &lt;a href="https://www.algoexpert.io/github-students" rel="noopener noreferrer"&gt;&lt;strong&gt;AlgoExpert&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MongoDB Certification&lt;/strong&gt;: Receive a 100% free certification voucher within 24 hours of completing any Learning Path on &lt;a href="https://learn.mongodb.com" rel="noopener noreferrer"&gt;&lt;strong&gt;MongoDB University&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Productivity &amp;amp; Design&lt;/strong&gt;: Free &lt;a href="https://www.notion.so" rel="noopener noreferrer"&gt;&lt;strong&gt;Notion&lt;/strong&gt;&lt;/a&gt; Education plan (extra sharing &amp;amp; AI features), 2,000 &lt;a href="https://www.slidecoach.ai/en" rel="noopener noreferrer"&gt;&lt;strong&gt;SlideCoach&lt;/strong&gt;&lt;/a&gt; AI presentation credits, and 60 &lt;strong&gt;Premium Icons&lt;/strong&gt; monthly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Business&lt;/strong&gt;: Zero transaction fees on your first $1,000 in revenue via &lt;a href="https://stripe.com" rel="noopener noreferrer"&gt;&lt;strong&gt;Stripe&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;And many more!&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33kp4s2bnskoaqbaomuu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33kp4s2bnskoaqbaomuu.gif" alt="GitHub student pack tools" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Claim Your Pack: Step by Step
&lt;/h2&gt;

&lt;p&gt;Getting access is straightforward, but the verification step requires a little attention to detail. Here is exactly how to get approved:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Prep Your GitHub Profile&lt;/strong&gt;&lt;br&gt;
Ensure your &lt;a href="https://github.com/settings/profile" rel="noopener noreferrer"&gt;GitHub profile name&lt;/a&gt; matches your student ID. If your account is named "DarkNinja99" with no real name attached, the automated system is going to be very suspicious. Use your real name!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Few46aqjqr6ptp318fggj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Few46aqjqr6ptp318fggj.png" alt="GitHub Profile" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Confirm Your Payment Information&lt;/strong&gt;&lt;br&gt;
Go to your &lt;a href="https://github.com/settings/billing/payment_information" rel="noopener noreferrer"&gt;Payment Information settings&lt;/a&gt; and include your full name, last name, address, city, country, and zip code. Don't panic, they will not request a credit card! This is simply required as part of the verification process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82fkpiykfhwks2pnvlno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82fkpiykfhwks2pnvlno.png" alt="Billing info" width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Enable Two-Factor Authentication (2FA)&lt;/strong&gt;&lt;br&gt;
GitHub requires you to secure your account. Head over to your &lt;a href="https://github.com/settings/security" rel="noopener noreferrer"&gt;Security settings&lt;/a&gt; and enable 2FA via the &lt;a href="https://github.com/settings/two_factor_authentication/setup/intro" rel="noopener noreferrer"&gt;setup page&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffs4qmbige1hvem2sqiof.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffs4qmbige1hvem2sqiof.png" alt="2FA" width="800" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Add Your School Email&lt;/strong&gt;&lt;br&gt;
Go to your &lt;a href="https://github.com/settings/emails" rel="noopener noreferrer"&gt;GitHub account settings&lt;/a&gt; and add your school issued email address. Verify it. (A school verification email is required for the most efficient process).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0yadz0ys5b4uwxwv4hi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0yadz0ys5b4uwxwv4hi.png" alt="Email verification" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt;&lt;br&gt;
Head over to &lt;a href="https://education.github.com/pack" rel="noopener noreferrer"&gt;education.github.com/pack&lt;/a&gt;, click "Sign up for Student Developer Pack". Select your role in education as "Student" ,and select this school email as an academic domain associated with your school/university.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fym44w1x4cwmd5ta9evwm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fym44w1x4cwmd5ta9evwm.png" alt="Education benefits Application" width="455" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Application Submitted&lt;/strong&gt;&lt;br&gt;
Your application has been submitted successfully! If needed earlier in the process, you may have used your webcam to snap a picture of your Student ID or transcript.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbmwpniq14ysqt2ha1c6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbmwpniq14ysqt2ha1c6.png" alt="submitted application" width="479" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7: Wait for the Magic&lt;/strong&gt;&lt;br&gt;
Once you submit, the initial review process generally takes between 48 to 72 hours. Using a valid school-issued email address is the most effective way to speed up this phase. Welcome to the big leagues!&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpzqxdefpbxkh1lb61jms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpzqxdefpbxkh1lb61jms.png" alt="Education benefits pending" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Ultimate AI Workbench: VS Code and GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;One of the absolute best perks of the Student Pack is free access to &lt;a href="https://github.com/copilot" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub Copilot Pro&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Having Copilot tightly integrated into your IDE feels exactly like having an endlessly patient, 10x senior engineer sitting right next to you, pair-programming. It doesn't just format your text; it understands your intent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before We Take Off (The Prerequisites):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VS Code 1.99+&lt;/strong&gt; (or version 1.116+ to have the magic built right in).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Copilot + Copilot Chat extensions&lt;/strong&gt; installed (if you're running pre-v1.116).&lt;/li&gt;
&lt;li&gt;An active &lt;strong&gt;GitHub Copilot subscription&lt;/strong&gt; (which you just scored for free with your Student Pack!).&lt;/li&gt;
&lt;li&gt;Make sure you are signed into your authenticated GitHub account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Give It a Mission!&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Here comes the fun part. Tell your agent what you want to accomplish (e.g., &lt;em&gt;"Refactor the database connection logic in &lt;code&gt;src/&lt;/code&gt; to use the new connection pool pattern and ensure all tests pass"&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;Now sit back, sip your coffee, and watch it autonomously navigate files, write code, run tests, and fix errors!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this setup, you're not just writing lines of code anymore you're architecting solutions while your AI pair-programmer handles the manual labor.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tips to Maximize Your Pack
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Don't Hoard, Use!&lt;/strong&gt; The free cloud credits (like DigitalOcean and Azure) are a use-it-or-lose-it investment in your education. Deploy a portfolio site or spin up a backend server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snag a Free Domain:&lt;/strong&gt; Pair your free domain from Namecheap or .tech with your hosting credits to deploy live, working projects. Recruiters &lt;em&gt;love&lt;/em&gt; seeing live sites!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turbocharge Your Learning:&lt;/strong&gt; Use your free access to platforms like &lt;strong&gt;Educative&lt;/strong&gt; or &lt;strong&gt;Frontend Masters&lt;/strong&gt; to dive deep into modern frameworks and algorithms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Your Secrets:&lt;/strong&gt; Get comfortable with tools like &lt;strong&gt;1Password&lt;/strong&gt; (included in the pack) from day one. Good security habits start early!&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The GitHub Student Developer Pack is more than just free software; it's a massive sandbox for your coding career. By leveraging tools like VS Code and GitHub Copilot, you can learn faster, build bigger, and code smarter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stop writing code that only lives on your laptop. Claim your pack, build something real, and launch it to the world!&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Got questions about getting set up? Drop them in the comments below! Happy coding!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>github</category>
      <category>vscode</category>
      <category>githubcopilot</category>
    </item>
  </channel>
</rss>
