New Tools, New Workflows and the Value of the Visual Studio Subscription: What We Learned at VSLive! San Diego


VSLive SD recap blog banner imageWhat happens when developers who have spent decades working with Visual Studio start rethinking how they write code, learn new skills, and expand their access to development tools? 

At VSLive! San Diego, we had an opportunity to find out as developers gathered for five days of technical sessions, hands-on learning, and conversations about Visual Studio, .NET, AI, cloud, data, and modern application development.  

One of the most interesting things we heard in San Diego was how readily experienced developers are adopting new tools and workflows. 

GitHub Copilot is part of that story, and developers aren’t limiting themselves to a single AI experience. They’re building broader, more differentiated tool kits. But they aren’t necessarily replacing familiar tools. They’re expanding how they work, choosing different experiences depending on the task, and finding new ways to solve problems.  

This is why events like VSLive! provide such an amazing opportunity for developers tackling these kinds of changes. Not only do they get to learn from expert led sessions and hands on labs, they get to learn from each other. 

AI is changing how developers approach unfamiliar problems 

One of the best parts of this event was being able to explore how developers learn new technologies and work through challenges.  

AI is increasingly becoming an early step in that process. 

Developers are using AI to research unfamiliar topics, understand existing code, troubleshoot problems, and explore possible approaches before deciding what to try next. 

But they aren’t relying on AI alone. 

They still move between documentation, technical videos, sample code, and hands-on experimentation to develop a deeper understanding of what they’re building. And a significant number of participants shared that hands-on learning was a preferred way to learn. 

That stood out to me. 

Even as developers adopt AI-assisted workflows, they continue to value opportunities to work directly with technology, test ideas, and understand how things behave. AI may help developers get started faster. Experimentation helps them decide what to do with what they’ve learned. 

The suite of benefits offered through a Visual Studio Subscription complements this developer journey, not only by providing significant discounts at VSLive! events, but also through access to learning paths, Azure credits, certifications, and hands-on labs.  

More generated code means more to evaluate 

Another interesting observation was how AI is changing the work that happens after code is written. Developers told us AI helps them produce code faster, but that doesn’t necessarily mean they’re spending less time on development. 

Instead, they’re spending more time reviewing and validating generated code. Does it work as expected? Does it fit the architecture? Is it secure? Can someone maintain it later? 

These questions have always mattered. AI-assisted development makes them even more important as developers evaluate code they may not have written themselves. 

AI can accelerate development, but developer resourcing and judgment remains essential. 

Time is still the biggest obstacle to learning 

With so many learning resources available, you might expect developers to struggle with finding the right information. But our conversations with developers at VSLive! San Diego signaled that the biggest barriers to learning new skills are time and the pace of technological change. 

Sometimes developers need a quick explanation to move forward. Other times, they need a course, a technical session, a community, or an environment where they can experiment. 

That helps explain why the flexible learning environment at VSlive! matters now more than ever. And it’s another reason Visual Studio Subscription benefits remain valuable. They aren’t just about the software developers use today. They can also help support the technologies and skills developers want to explore next. 

Let’s keep the conversation going 

What stood out most from San Diego was the combination of experience and curiosity. We met developers who have used Visual Studio for decades and are actively exploring how AI can change the way they build software. 

They’re adopting new tools, reconsidering familiar workflows, and looking for more opportunities to experiment. And they’re helping us better understand what developers need as those workflows continue to evolve. 

That’s why the conversations we have at events like VSLive! matter. They give us a chance to hear directly from the people using our tools and help us better understand where we can improve. 

If you’d like to continue learning and connecting with the developer community, join us at future VSLive! events: 

  • Orlando November 15–20, 2026  

Thanks to everyone who joined us in San Diego, and especially those who shared their experiences and ideas. The tools developers use are evolving quickly. Hearing how developers are adapting helps us understand what we should build and improve next. 

The post New Tools, New Workflows and the Value of the Visual Studio Subscription: What We Learned at VSLive! San Diego appeared first on Visual Studio Blog.

Building the new GitHub Copilot Inline Suggestions Model: Part Two


September 23, 2026 by Julia Gong, Shengjie Ma, Ben Liggett, and Ulugbek Abdullaev

Completion-style ghost text, next edit suggestions near the cursor, and edits farther away were previously powered by separate models. We built one model for all three, and learned that the best results come from training, evaluation, and editor design evolving together.

Phase 2: The 3-in-1 model

In the first part of this blog post, we shared the first phase of the unified modeling effort: unifying the NES and long-distance edit behavior into a single 2-in-1 model.

The unification strategy diagram showing the stagewise merge from completions, NES, and long-distance edit models into the 2-in-1 model and then the final 3-in-1 model.

Figure 1. We first unified the NES and long-distance NES models to yield the 2-in-1 unified model, followed by unifying the 2-in-1 model with the completions model to yield the 3-in-1 model.

The next step was to bring completion behavior into the 2-in-1 model. Previously, an edit opportunity could involve a completion request followed by another request for a richer 2-in-1 model edit. With the fully unified 3-in-1 model, one request can consider the full range of code editing behaviors and decide the best response at any given moment, or chain many of them together in a single response.

This greatly reduces model calls and serving complexity, but the biggest benefit isn’t even the efficiency. A single model can optimize for the best edit that fits the moment instead of preserving the artificial boundaries that resulted from the system architecture.

Case in point, in our final 3-in-1 model candidate, we found that while the proportion of less-intrusive ghost text decreased in the 3-in-1 model compared to the 2-in-1 model setup, there were actually significant measurable improvements in user satisfaction. We will talk more about this later in this post.

Training the v4 models: adding in completions

To train the 3-in-1 model, we applied what we learned while developing the 2-in-1 model. As the goal was to add completion behavior to the 2-in-1 model, the distribution of the training data needed to change. We gathered ghost text completions data through a variety of techniques, including distilling ghost text from the original completions model and filtering them for quality using an LLM judge. We leveraged the original training recipes from the 2-in-1 model while adding this new ghost text data.

We also had to carefully rebalance the distribution of the multi-edit data inherited from the 2-in-1 model recipe. Models that showed too little ghost text or were too eager to jump away from the user’s cursor often resulted in more disruptions to the user flow and thus higher dismissal rates. This naturally gave rise to a dedicated subset of multi-edit data where the first patch was a ghost text completion at the user’s cursor. During RL, as mentioned earlier in part one, we also kept the grader design that encouraged the model’s edit sequences to begin with the most immediate continuation of the developer’s work, then move outward to related follow-up changes, which made edits least intrusive and kept more logical flow and continuity.

Early model candidates produced ghost text more often and more suggestions overall as a result. We measured these results offline with three benchmarks discussed in part one: STests, Output View Kind, and Pseudo-Online Evaluation. We also noticed that the HumanEval benchmark results improved because of having stronger completions capabilities.

When we flighted these v4 models against the now-production setup of the 2-in-1 model and the completions model, results were quite promising: no statistically significant changes in acceptance rate, dismissal rate, shown rate, and user engagement metrics. But we did find a marginally statistically significant regression in accumulated retained characters, or the number of characters that were not reverted by the user within a certain time interval after accepting a suggestion.

We considered several potential causes of this regression, including poorer suggestion quality, but because of the lack of movement in other metrics, we ultimately pulled the thread on one hypothesis in particular: suggestion length.

Training the v5 models: ghost text completeness

Our hypothesis was that because the model was producing slightly shorter ghost text suggestions compared to the production completions model, users might be accepting promising but incomplete suggestions. As a result, they might be more frequently reverting or editing the suggestions. For instance, writing the function signature and docstring is nice, but if we don’t follow through with the full implementation, then the user might remove the function, make edits, or rewrite it manually.

To test this hypothesis, we applied what we learned from the 2-in-1 model’s insertion challenges and gathered a subset of data that specifically targeted this type of longer-output scenario and performed a similar upweighting of the data. We further added another auxiliary grader dedicated to ghost text completeness and gated it to these specific curated samples. To measure the offline impact of this change, we also introduced a second version of the Output View Kind dataset that measured the character lengths and proportion of ghost text in model responses compared to the original distribution of the production model.

We flighted our most promising model candidate and were pleased to see that the regression in accumulated retained characters had decreased but was not eliminated, and the dismissal rates were trending higher. However, there were several observations made during the dogfooding experience that led us to look beyond the model itself. This reinforced an important lesson we had learned through iterating on our previous models: client behavior is just as important as the model.

The model is part of a larger end-to-end experience

The ultimate user experience is much more than just the model’s capabilities: a great inline suggestions experience is the fusion of a great model with a great end-to-end system. Careful client orchestration is also necessary to show edits to the user at the best time and in the best way.

For example, when dogfooding the most promising 3-in-1 flight candidate, we noticed an important past client behavior decision for NES that was worth revisiting. When ghost text was shown to the user but ignored, if the user moved their cursor to a different location, that cached ghost text suggestion would be re-shown as an NES edit. Upon deeper investigation, we estimated that this client behavior alone could potentially be responsible for inflating the 3-in-1 model’s dismissal rate by 7-8%. Once we ablated this issue in an A/B flight, we found the impact was even larger than we had estimated—the dismissal rate went from a 15.9% increase to a 10.1% decrease—a 26% difference—compared to the production 2-in-1 setup.

The reason for this behavior requires some historical context. Originally, the standalone NES model’s suggestions could arrive asynchronously as the user moved their cursor, whereas the standalone completions model’s ghost text disappeared when the cursor moved away. As a result, the ghost text from the standalone NES model was intentionally made persistent so it could be shown as the user moved their cursor. However, because the 3-in-1 model identified itself to the client as an NES model, it inherited this behavior despite its ability to also provide completion-style ghost text at the cursor. By ablating this NES ghost text persistence behavior through a client setting, nesMimicGhostTextBehavior, we were able to revisit and change this behavior to make a choice that best fit the new model behavior. This underscores the importance of experimenting with the feature end-to-end in the client—new models have new behavior, which might warrant different client settings.

Beyond this ablation study, we also did extensive testing to make the best client-side choices for the 3-in-1 model’s edits, including optimizations in edit caching, speculative decoding, how to render the edit to the user, and progressive reveal of longer edits. Through multiple rounds of internal dogfooding and A/B testing, we discovered that each of these client choices made a big impact on the user experience.

We evaluated five client-side optimizations as a joint configuration that resulted in the best end-to-end unified model experience:

  1. Speculative decoding: The prior standalone NES model already used speculative decoding to reduce suggestion latency, but the new unified model output format required us to revisit what output should be speculated. We ablated several variants of the speculated text with progressively stronger guidance toward completion behavior: only the file path header (without specifying any line, the default used for the 2-in-1 models), replacing the current line (specifying the current line but not a particular view kind), and completing the current line (specifying both the current line and the ghost text view kind). After load testing, latency analysis, view kind distribution analysis, and online flights comparing these options, we chose to speculate completion at the current line, which yielded the lowest suggestion latency without negatively impacting the user experience.

  2. Ghost-text progressive reveal: Progressive reveal shows the immediately relevant portion of a longer ghost text suggestion first, then progressively reveals the remainder. This prevents the user from navigating a long block of text while making incremental progress on their work. Progressive reveal of ghost text was a critical client feature that underwent several rounds of optimization for the original standalone completions models, and its functionality was extended later to the standalone NES models—we thus ported over this technique to the unified model client behavior.

  3. Diff-based edit rendering: For the standalone NES models, the client would take parse the code in the rewritten window to determine the code diff and thus the corresponding view kinds to show the edits to the user. This was required because raw rewritten code had to be parsed to show a minimal edit to the user. However, for the unified models with diff patch output formats, we had a choice—should we display the view kinds implied by the raw patches themselves, or perform this diff-based rendering per-patch as well? Earlier, we found that the model may generate suboptimal-efficiency patches in exchange for better overall suggestion quality (see the discussion on patch validity in part one of this post). For instance, the model might produce the following patch:

    aquarium.py:2
    -cuttlefish
    +axolotl
    +blobfish
    +cuttlefish
    +dolphin
    

    If we used the raw patch, we would show a side-by-side “diff” view kind to the user, where cuttlefish is replaced by axolotol, blobfish, cuttlefish, and dolphin. However, if parsed, this could be optimized so that the user first sees this insertion ghost text:

    aquarium.py:2
    -cuttlefish
    +axolotl
    +blobfish
    +cuttlefish
    

    Followed by this insertion on a different line:

    aquarium.py:4
    -cuttlefish
    +cuttlefish
    +dolphin
    

    Thus, we hypothesized rendering might serve as another safeguard in case there were an even stronger way to present the edit to the user than what was implied by the model output. Through online A/B experimentation, we found this was indeed a positive change for the user experience. Thus, we first interpret each change in the patch and then present it through the appropriate rendered interaction (for example, ghost text, a nearby rewrite, a farther rewrite, a cross-file suggestion, or no suggestion), rather than rendering edits based on the model’s raw patch structure.

  4. Cache delay and debounce settings: Immediate presentation of suggestions can be disruptive when they arrive too quickly, which results in a worse user experience. A slight delay before presenting a cached suggestion better matches the developer’s typing rhythm to help them stay in-flow, especially with the decreased suggestion latency from optimizing the speculative decoding. This setting was already in use, and we ablated several configurations of cache delay durations to arrive at a configuration tailored to the unified models. We did the same for debounce settings—whether to delay calling the model for a suggestion while the user is still typing—and found that immediate model invocation while the user was still typing did not result in a worse experience.

  5. Cross-mode ignored suggestion suppression: As discussed above, this prevents ignored ghost text from immediately resurfacing as a next edit suggestion after the cursor moves. To the system, these may be different views, but to the developer, they are the same unwanted suggestion.

This work underscored a point that applies across interactive AI systems: ultimately, a good model is just one component of a complex system—UX, client logic, networking, and server-side logic, to name a few—and all parts of that system must be designed with care and optimized intentionally to create a great experience for the user. The end-to-end experience is the product.

Takeaways and learnings

Folding completions into the unified model had a much higher development velocity because it built directly on the 2-in-1 foundation, showing how compounding learnings accelerate each strategic phase. A few lessons to call out:

  1. Build on successes. The ghost-text length regression was resolved with the same playbook from Phase 1: Targeted longer-output data, upweighting, and a dedicated auxiliary grader gated to completeness. Identifying successful patterns and reusing them when appropriate was critical.
  2. The model is only one part of an end-to-end experience. When changing the fundamental model behavior and the task formulation, some parts of the end-to-end system had to change as well. Some client behaviors were intentional choices optimized for the previous standalone NES model and needed to be revisited as the unified model took on completion behavior. Through careful experimentation, one such change—preventing ignored ghost text from resurfacing as NES suggestions—helped swing dismissal rate by 26%, from +15.9% to -10.1%.
  3. The beauty of unification. The unified 3-in-1 model saw a 10.1% drop in dismissals during online experimentation with no key metric regressions, despite showing 13% less non-intrusive ghost text. One model deciding the end-to-end best edit beat orchestrating independent specialists, illustrating that the unified experience is greater than the sum of its parts.

Beyond the individual model results themselves, another broader lesson we learned is the value of reflection and learning across the end-to-end system.

From a science perspective, the 2-in-1 model took our team over 15 SFT training runs, 170 RL training runs, and several times as many checkpoint-selection runs, resulting in 14 A/B flight candidates before the final shipping candidate. In contrast, the 3-in-1 model was developed using only RL on top of the 2-in-1 model, and it took us only 35 RL training runs and 10 A/B flight candidates. Each modeling milestone has benefited from, built on, and been accelerated by our learnings in previous ones.

This iteration extended far beyond the model itself. Over the same period, the VS Code client team made 113 PRs improving and supporting the NES experience, including the changes described earlier in this post. These spanned experimentation and configurability, model integration, prompting and context construction, serving and request orchestration, caching and rebasing, rendering and interaction, telemetry and observability, correctness and robustness, and the extensive ongoing work of keeping the experience running smoothly as it shipped to millions of users each week.

This is the reward of building the product as an end-to-end system: the model and the surrounding experience evolved together, with learnings from each continually shaping the other. The acceleration we see in the end-to-end system getting better at learning and improving is just as, if not more, exciting than any individual milestone itself.

The learning loop between the model and the full end-to-end experience.
Figure 2. The learning loop between the model and the full end-to-end experience is a two-way street, and evaluation and reflection at every step benefits all components of the experience.

Online results

We flighted the 3-in-1 model compared to the then-production baseline of the 2-in-1 model and completions model. We were excited to see a 10.1% decrease in dismissals with the new unified model without statistically significant regressions in any key metrics, including accumulated retained characters. This was especially notable given that the proportion of ghost text at the cursor decreased by 13% compared to the control, adding nuance to our prior learnings that increasing the proportion of less intrusive ghost text lowered dismissal rates.

This underscores the benefit of a unified model. The model can choose the best edit for the given context, often more effectively than complex client logic that orchestrates independent models. We consider this to be a promising data point to show that the unified experience can be greater than the sum of its parts.

We are excited for you to try this unified system that treats inline editing as one continuum, from finishing the current line to carrying a change through the rest of the file.

What’s next?

We hope you enjoyed this two-part deep dive into training the new unified inline suggestions models (and in case you missed it, you can find part one here: Building the new GitHub Copilot Inline Suggestions Model: Part One). Please also stay tuned for a more detailed technical report!

We are also working on expanding this model’s capabilities to make the code editing experience even more seamless and intuitive. This includes personalized model eagerness, which builds on our work in model quality by tailoring how proactively the model suggests edits to user preferences.

Try it out

The unified Inline Suggestions experience is available now for paid GitHub Copilot users in VS Code. Update to the latest version of VS Code, then make sure next edit suggestions are enabled.

Give it a try the next time you are in the editor, whether you’re working on a refactor or writing a new function. We hope you enjoy the tab-tab-tab experience, and we’d love to hear your feedback!

In the second part of this blog post, we’ll dive deeper into how we moved to the 3-in-1 model for inline suggestions. Stay tuned!

Happy coding! 💙

Acknowledgements

Special thanks to Luciana Abud, Alexandru Dima, Yu Hu, Simona Liao, Gaurav Mittal, Elsie Nallipogu, and Nick Trogh for their thoughtful feedback, insights, and contributions to this blog post.

We extend our deepest gratitude to our developer community for the ongoing feedback that pushes us to deliver the best possible experiences with VS Code and GitHub Copilot. Huge thanks to the researchers, engineers, product managers, and designers across GitHub and Microsoft who curated the training data, built the training pipeline, evaluation suites, and serving stack, and to the VS Code and GitHub Copilot teams for smooth model releases.

Visual Studio Code 1.141 (Insiders)


Follow us on LinkedIn, X, Bluesky, Instagram | Follow Insiders Changelog on X or Bluesky


VS Code Insiders banner.

Last updated: September 30, 2026

Welcome to the 1.141 Insiders release of Visual Studio Code.

These release notes cover the Insiders build of VS Code and continue to evolve as new features are added.

You can still track our progress in the Commit log and our list of Closed issues.

These release notes were generated using GitHub Copilot and might contain inaccuracies.

Happy Coding!


September 29, 2026


We really appreciate people trying our new features as soon as they are ready, so check back here often and learn what’s new.



Building the new GitHub Copilot Inline Suggestions Model: Part One


September 16, 2026 by Julia Gong, Ben Liggett, and Ulugbek Abdullaev

Completion-style ghost text, next edit suggestions near the cursor, and edits farther away were previously powered by separate models. We built one model for all three, and learned that the best results come from training, evaluation, and editor design evolving together.

At GitHub Copilot, our mission is to support all development workflows, from AI-assisted coding using inline suggestions to agent-first software engineering in the VS Code Agents window. Inline suggestions are used and loved by millions of developers, and we continue to push the quality bar on it and all GitHub Copilot experiences.

Writing code is rarely linear. The next useful change might be a few characters at the cursor, a nearby rewrite, or a related edit elsewhere in the codebase. Inline suggestions accommodate these different workflows through completion-style ghost text, nearby next edit suggestions, and long-distance edits.

Previously, specialized model paths powered each type of suggestion. The tried-and-true completions model doesn’t need much of an introduction, and in earlier posts, we shared how we trained a custom model for next edit suggestions and extended those suggestions to edits farther away. We have now unified all three models behind a single “3-in-1” model that can do it all.

Unifying the models improves suggestion quality by allowing a single model to choose the best edit for the developer’s current work end-to-end instead of using programmatic logic to choose among specialized models. For instance, let’s say the developer has typed class Fa in the penguin feeding program below. Using the previous standalone models (left), the most mature and battle-tested completions model is always triggered first. Since it can only append to the prefix Fa, it does what it knows best and suggests FastingPenguin. However, in this particular case, a better NES suggestion exists, as suggested by the unified model (right): semantically rewrite Fa to Fish.

Before (standalone models) After (unified model)
A code example where the standalone completion model chooses FastingPenguin instead of the better Fish rewrite. A code example where the unified model selects the better Fish rewrite for the same context.

Not only can we tackle all existing tasks in one model, but because this model can output multiple edits in one response, we can cache these additional edits to deliver a faster experience for subsequent edits if the preceding suggestions were desirable. This creates a smoother, snappier tab-tab-tab experience across the editing flow.

To enable this better editing experience, we first reframed the modeling task—especially the prompt and output format—to generalize across code editing tasks. We then combined our learnings in data quality, model training and evaluation, and client design from the standalone models, in addition to extensive additional experimentation (over 200 offline and 20 online experiments, whose course we will chart in the remainder of these posts), to carefully optimize the model and end-to-end experience. The result is a higher quality, faster, and more cohesive typing companion that is greater than the sum of its parts.

An animation of a VS Code coding experience with ghost text and fast follow-up tab-tab-tab suggestions showing the unified inline suggestions experience.

Why unify?

Prior to the unified model, the production implementation of inline suggestions in VS Code was powered by three separate models:

  1. Completions (the familiar ghost text we all know and love),
  2. NES (next edit suggestions, or nearby edits bounded by a few lines above and below the cursor position),
  3. Long-distance NES (longer-range NES-style suggestions farther from the cursor).

This dedicated work on individual tasks, with a highly mature completions model alongside newer editing models, resulted in a client-orchestrated experience that triggered each where appropriate.

While effective for these individual tasks and a necessary step to bring new editing capabilities to users, this created key shortcomings not only in terms of user flow quality (sometimes making suboptimal or piecemeal edits rather than a single clear edit that best serves the context) and latency (potentially up to 4 model calls per opportunity, as shown in the figure below), but also in terms of extensibility to future features (for example, multi-file edits).

Standalone models diagram showing separate completion, NES, and long-distance NES call paths.

Figure 1. The original stepping-stone production setup for VS Code inline suggestions with three standalone models: completions, NES, and long-distance NES. Note that this diagram is simplified for clarity and represents the behavior from a user’s perspective (real provider calling behavior is more complex and involves issuing parallel calls to completions and NES, for instance, depending on the position of the user’s cursor and how quickly the prioritized model responds). Each model handled its own standalone task, while the client orchestrated the logic of when to trigger which model. The completions model would always be triggered first to predict ghost text at the user’s cursor, which would be shown if ghost text was generated. If no ghost text was produced, the NES model would be invoked to rewrite the window around the user’s cursor, and shown using the appropriately rendered view kind if the rewrite resulted in a net edit. If still no edit was predicted, the long-distance edit model was triggered to predict a potential line number to jump to. If no line number was produced, no edit would be shown. If it did jump to a new line number, the NES model would be invoked once more to rewrite a window around the long-distance line number, resulting in a long-distance NES edit.

Unification also creates a compounding benefit. With one shared model powering every inline suggestion, each model improvement or new model feature can now benefit the full experience rather than remaining isolated to a single suggestion type.

Reformulating the code editing task

Knowing that a unified model was the north star, we realized this was an opportunity to reformulate the code editing problem, starting from the model output format. None of the three individual siloed tasks of predicting a suffix (completions), a window rewrite (NES), or a line number (cursor jump), which we had solved systematically and individually over time, were sufficiently expressive to represent the other tasks entirely. To combine these into a single model that could do all three, we needed a similarly unified output format—this gave rise to an elegant solution that we call the “diff patch” output format.

Consider a developer changing a function signature. The next useful action may be completing a new argument at the cursor. A moment later, it may be updating a call site below. After that, it may be adjusting validation logic elsewhere in the file. These are different interactions, but they are part of one editing task. A shared patch language lets the model reason about them as sequential steps of the same problem, which can be presented to the user with greater fluidity.

To fully understand the model output format changes, one can think of the three individual model tasks each as natural extensions of LLM next-token prediction capabilities—completions continued unfinished code, NES rewrote a local edit window, and long-distance edits predicted the next line number to jump to, accompanied by a call to NES. The 3-in-1 model puts these together to tackle all three at once while allowing the model to predict multiple edits in one pass.

To make this concrete, consider this example, where the symbol <|cursor|> represents the position of the user’s cursor.

def feed_penguin(penguin, fo<|cursor|>):
    penguin.meals += 1
    penguin.hungry = False
    penguin.last_ate_time = datetime.now()

    print(f"{penguin.name} ate {fish.type}")

penguin = Penguin("emperor")
feed_penguin(penguin, fish="silverfish")

The completions, NES, and long-distance edit models might predict the following in isolation to make the best edit for their corresponding tasks:

Completions format NES (Window Rewrite) format Long-Distance Edit format
od
def feed_penguin(penguin, food):
    penguin.meals += 1
    penguin.hungry = False
    penguin.last_ate_time = datetime.now()

    print(f"{penguin.name} ate {food.type}")
5 (the next line number where fish should be replaced with food)

The diff patch output format puts all of these elements together into a chain of edits that makes most sense at the cursor, farther away from the cursor, and even in a related file:

/path/to/penguins.py:0
-def feed_penguin(penguin, fish):
+def feed_penguin(penguin, food):
/path/to/penguins.py:5
-    print(f"{penguin.name} ate {fish.type}")
+    print(f"{penguin.name} ate {food.type}")
/path/to/penguins.py:8
-feed_penguin(penguin, fish="silverfish")
+feed_penguin(penguin, food="silverfish")
/path/to/antarctica.py:42
-feed_penguin(penguin2, fish="krill")
+feed_penguin(penguin2, food="krill")

Multi-patch responses also importantly allow us to cache subsequent patches (in the example above, the edits at lines 5, 8, and 42). Upon acceptance of preceding patches, they can appear with low latency, which results in a fast tab-tab-tab code editing experience.

This format expresses the three previous tasks in full and allows for flexibility in elegantly expressing future behaviors like cross-file edits (edits suggested in a related, but different file from the current one). More general formats such as tool calls are more abundant in pretraining and support actions beyond editing, but for code edits, we found that this format is most compact while remaining expressive.

In addition to reformulating the output task, we also took the opportunity to revisit the context given to the model as input. Originally, the input to the model included:

  1. Recently viewed code snippets without line numbers
  2. Current file content with line numbers
  3. Recent edit history of the user in unified diff format
  4. Area around the code to edit, a total of +/- 15 lines around the user’s cursor to pad the code to edit region
  5. Code to edit, the rewrite window spanning 2 lines above and 5 lines below the user’s cursor

The unified output format enabled us to simplify the input context as well. Because the task scope now allowed for arbitrary edits anywhere in the file and was not limited to predicting the suffix at a specific location or rewriting a fixed window, we could remove the last two sections of the input—area around the code to edit and code to edit—and instead replace it with a single 3-line block with the line number and file content of the current cursor location. One important learning we carried forward from the previous models was that since the user’s cursor is constantly changing positions, we kept the cursor location section at the end of the prompt as opposed to directly placing it inside of the current file content. This optimizes key-value caching by maximizing the common prefix of the prompt with previous prompts.

We wanted to tackle the problem of unification methodically, so we approached it in two phases. First, we unified the NES and long-distance capabilities into a single model with the unified diff patch format, which we refer to as the 2-in-1 model. The completions model was left intact, and the client orchestration logic was simplified to prioritize completions, followed by the 2-in-1 model. We then unified the 2-in-1 model with the completions model to bring in the ghost text capabilities to arrive at the 3-in-1 model. We’ll describe our experimental process and share some of the methods we developed, challenges we encountered, and learnings we gained along the way.

The unification strategy diagram showing the stagewise merge from completions, NES, and long-distance edit models into the 2-in-1 model and then the final 3-in-1 model.

Figure 2. We first unified the NES and long-distance NES models to yield the 2-in-1 unified model, followed by unifying the 2-in-1 model with the completions model to yield the 3-in-1 model.

Phase 1: The 2-in-1 model

We deliberately chose to first tackle NES and long-distance edits before completions. In our experience, the completions model accounted for most of the inline suggestions traffic—higher than 70% of edit opportunities. Previous experimentation from the team also showed that NES suggestions were more prone to user dismissals than ghost text. Thus, we chose to first unify the two other models and tackle the flagship completions model last. Because the diff patch output format could be used for the 2-in-1 model, this also meant that later training for the 3-in-1 model could directly take advantage of the data and other learnings from the 2-in-1 model, accelerating experiment velocity.

Evaluation

To build a good system and improve it, we must start by deciding what we want to measure. No single score captures the quality of an inline suggestions model. We therefore used four complementary stages of evaluation, similar to the process we used for earlier next edit suggestion releases.

  1. Offline evaluation: Targeted offline tests helped us inspect completion behavior, difficult editing scenarios, patch validity, suggestion length, and the balance among different types of edits.
  2. Internal dogfooding: Daily use exposed issues that aggregate scores could miss, such as suggestions that were reasonable but poorly timed, too eager, incomplete, or awkwardly presented.
  3. Human evaluation at scale: We also did human evaluation with programmers of diverse backgrounds on thousands of coding tasks using structured feedback templates to get a quantitative assessment of model quality from real developers.
  4. Controlled online experiments: Promising model candidates were flighted live using A/B testing so we could evaluate the ultimate impact of the model on real users.

Each stage answered a different question. Offline evaluation told us whether a candidate was worth testing. Dogfooding gave us a firsthand perspective on how it felt in realistic workflows. Human evaluation quantified the dogfooding experience and provided structured feedback. Online experiments told us whether the complete system created value in use compared to the existing production setup.

Offline benchmarks

Offline evaluation for the original NES models consisted primarily of 3 benchmarks, which each assessed different dimensions of the NES models:

  1. Simulation Tests (STests). A manually curated set of workspace recordings from our team that demonstrate must-have, nice-to-have, and must-avoid suggestion behaviors.
  2. HumanEval. An augmented version of the HumanEval dataset from OpenAI that was expanded to evaluate models’ completion capabilities on single-line, multi-line, and random spans of code.
  3. Output View Kind. Examples passed through prior production models, including the view kinds (ghost text, side-by-side NES, no edit, etc.) of the models’ output, used to track any differences in the distribution of view kinds produced by new candidates compared to the original models.

Training the v1 models: Diff-patch NES

We began by building tools to robustly convert the original NES model evaluation and training data into diff patch format. Once the data was converted, we trained some initial supervised fine-tuning (SFT) models, followed by reinforcement learning (RL) on the NES-only training data—let’s call this round of models the v1 models.

As we expected, the resulting models could perform on par with the NES models in offline benchmarks, but the distribution of edits they learned was exactly that—NES edits, with almost no long-distance edits. We also discovered that the difference in data formats, despite using identical data samples, sometimes resulted in different behaviors. For instance, edits tended to be more incremental, which might be due to the diff patch format naturally expressing targeted changes at specific locations instead of rewriting an entire target window (this will come up again later when we discuss the 3-in-1 model). Upon flighting these models, we also discovered several client-side nuances for handling this new output format, including caching and error handling, that were refined early so that future model candidates could benefit from this dry-run.

Now it was time to fold in long-distance edits. In the diff patch formulation of the problem, an elegant property emerges for the long-distance NES case: An NES edit + a long-distance NES edit = a multi-patch response. Multi-patch responses were also critical to add because of the user experience economies of scale that come with caching subsequent patches for fast follow-up edits.

But how were we going to get multi-patch responses when our existing models did not have multi-patch capabilities?

Training the v2 models: Adding in long-distance NES

Folding in long-distance edit capabilities wasn’t trivial because the sets of existing data for long-distance edits and NES were not joinable, as they were from completely different files and edit histories. We needed to bootstrap multi-edit data from the single-edit data. We ultimately came up with two approaches to solve this problem:

  1. Bootstrapping responses using v1 model pseudolabels. We first fast-forwarded the diff patch-format NES data by moving the output label into the edit history. We then fed this fast-forwarded data back into the best v1 models that we trained. If the model produced an edit response, we appended this pseudolabel to the original data’s output label as another patch. We continued to repeat this process until the v1 model produced no edit in its response. This yielded samples with n patches that we could then teach the model to produce. See the figure below for details.
  2. Edit playback. We parsed the NES data model input, which contained user edit histories, and used those edits to “rewind” the state of the workspace file by anywhere from 1 to n edits. We then removed those edits from the edit history in the input and prepended them to the output.

A diagram showing the multi-patch bootstrapping techniques used to generate multi-patch data from single-patch data.

Figure 3. Two processes by which we repeatedly bootstrapped multi-patch data by fast-forwarding single-patch data. Top: We first fast-forwarded the data with n patches in the output by moving the output label into the edit history. If the model produced a response for this fast-forwarded sample, that output would be added to the original sample’s output label to create a response with n+1 patches. Bottom: We performed edit playback by moving recent edits from the edit history to rewind the session state and predict them as part of the model output.

After these approaches yielded enough data, we then filtered the data using an LLM-as-a-judge and rules-based quality filter. The criteria in this filter were distilled from our understanding of developer preferences throughout the development of our preceding code editing models, such as correctness, necessity, and intent and edit history alignment, and the rules-based filters accounted for patch validity and undesirable behaviors like code duplication.

We then used SFT to train a new model on a new mix of this data and the previous NES data, which yielded models that produced 1.3 to 1.4 patches on average, compared to the original near-1 averages. While this number might sound small, we later found this is a sweet spot that makes a significant difference in the user experience without degrading quality. After all, to get an average of 2 patches per response, long-distance edits would need to happen on average at every edit opportunity, which was not the case in the existing production setup with a dedicated long-distance edit model.

RL was applied to the v2 SFT models in a similar fashion, using the same techniques to bootstrap multi-patch data. The grader logic was also altered to incorporate guidance for multi-patch responses. We found this model had much stronger offline results compared to the SFT model.

Patch ordering

When there are multiple edits, the natural question of how to order them comes up. This was also a deliberate choice we made.

During data filtering, in addition to the criteria for edit quality, we also added a new criterion targeting edit ordering requiring a smooth logical flow of the edits through the file in order of priority and proximity to the user’s cursor. This choice sounds intuitive because it was distilled from our experience in orchestrating the three standalone models in the client. The logic was to first query the completions model, followed by the NES model, followed by the cursor jump model and a subsequent NES model call if the cursor jump model chose to jump.

In addition to including these criteria in the data filtering pipeline, we also included them in the RL grader with some additional nuances in the reward function, which we observed was important for prioritizing logically coherent edits.

The Pseudo-Online Evaluation benchmark

The v2 models were a step-function improvement compared to the v1 models in online A/B testing compared to the production three-model control. Aside from the dismissal rates being elevated, all other metrics like acceptance rate, shown rate, accumulated retained characters, and user engagement metrics had no statistically significant movement. But one strange finding emerged: offline results were not very predictive of the online results. One of the strongest offline candidates with the highest-ever score in STests, for instance, did not do as well as another with lower STests in the A/B flight. This got us thinking: how do we close the gap between our offline and online results so we can iterate on model candidates more efficiently and confidently?

The result was a fourth offline benchmark that we call the Pseudo-Online Evaluation (POE). The benchmark consists of three equally-sized sample buckets representing acceptance, rejection, and no edit cases from production model outputs, along with suggestion quality signals. The benchmark runs each of the samples in these groups through the candidate model. It then uses an LLM judge using in-context learning to determine whether the candidate response would be accepted or rejected given the known outcome of that sample.
The most critical metrics that arose from this benchmark were the reject rate (lower being better), accept-to-reject-rate ratio (higher being better) and the ratio of rejects that became no edits to the accepts that became no edits (a measure of whether the model learned to abstain more for previously poor responses without losing previously good responses). We also quantified issues like patch validity errors, which we will talk about later, and other metrics, such as the number of patches in responses. These metrics, while admittedly still not a perfect proxy, became a stronger predictor of online performance for subsequent model candidates.

Grader and quality filter calibration

Developing the POE benchmark also raised another question: were we leaving anything on the table with our new diff patch-specific RL graders? Could we improve it using additional data and quality signals?
We decided to try to calibrate the grader better to user feedback by taking a self-refinement approach to the grader. We developed an agent skill that performed the following loop:

  1. Take the samples from POE and run them through the grader to get the grader’s judgment on the production model response.
  2. Construct the confusion matrix of false positives, false negatives, true positives, and true negatives after running all samples.
  3. Randomly sample examples from each category to understand common failure modes of the grader and patterns in its blind spots.
  4. Adapt the existing grader instructions to incorporate any observed feedback that clearly formed a pattern.
  5. Repeat.

It is worth noting that the quality signals we use are oftentimes noisy. However, through this process, we were able to automatically increase concordance between the RL grader and these quality signals, reducing false negatives by 8.4% and false positives by 1.1%. This improved the reliability of our training, evaluation, and data filtering pipelines.

Tackling invalid patches

Later v2 model variants benefited from the updated RL grader and better offline model selection, but a few other challenges emerged as we dogfooded the models more regularly. One of these challenges was invalid patches.

We noticed that the model would sometimes create patches that were malformed or introduced mistakes that were programmatically verifiable. We characterized patch validity with two tiers: critical issues that impact the user experience, and suboptimal patches that are token-inefficient. We developed fine-grained rules-based filters to catch these issues. An example of a critical issue is duplication of code in the lines preceding or following the line where the user’s cursor is. These are visible to the user and negatively impact the suggestions they receive. In contrast, an example of a suboptimal issue is no-op patches, or patches where additions and deletions are perfectly matched; in other words, patches that completely undo their own work. These were wasteful from a token and latency perspective, but not detrimental to edits presented to the user.

Incorporating these rules-based patch validity checks into the RL grader did decrease the proportion of invalid responses, but it improved less than expected. We turned to examining the distribution of data in our RL dataset and hypothesized that it did not capture the common contexts in production that led to these model errors. To validate this suspicion, we conducted targeted data mining on examples from the latest v2 models that triggered patch validity failures. We ran the responses through our patch validity checks, repaired them automatically using an iterative LLM feedback loop guided by those checks, and filtered the repaired samples for quality. By carefully experimenting with the sampling ratio of these examples during training, we were able to reduce patch validity issues without negatively impacting other scenarios.

One last thing we ablated for the patch validity checks was whether to penalize both critical and suboptimal issues, or just the critical issues. We hypothesized that allowing the model to produce suboptimal patches might clean up the reward signal for reducing critical issues and also have unexpected benefits (e.g., a no-op patch between two valid patches might almost serve as a ‘chain of thought’ as the model thinks through possible edit locations). Indeed, once we removed the penalty for suboptimal patches, we did see more consistent reduction in critical issues without significant detriments in other offline quality metrics.

Training the v3 models: Tackling issues in insertion pattern propagation

As we got closer to a strong shipping candidate, one other persistent issue presented itself through dogfooding: misplaced insertions during pattern propagation, and specifically, correct content with incorrect placement. This was a very specific failure mode of the v2 models when the appropriate response would be to insert new content at another location in the file to propagate a pattern of repeated insertions following user intent. For instance, if the user added the field password after email in a web form, the expectation would be to add the corresponding Password label after the Email label, and a validate_password check after the validate_email check. However, the v2 models were found to frequently place Password before Email, or even at the very bottom of the list of fields.

Building on our learnings from suppressing invalid patch behavior, we approached this problem in two ways.

First, we used LLM judges to identify examples from the v2 model outputs that exhibited this specific failure mode: generating the correct content but placing it incorrectly when user intent implied pattern propagation. This proved surprisingly difficult because long-distance insertion scenarios were relatively rare compared to replacement scenarios. Even after LLM-based response repair and quality filtering, we obtained thousands of positive examples, but only a few hundred negative examples exhibiting the original placement error.

Diagram of the data mining workflow used for targeting problematic behaviors.

Figure 4. The data mining workflow we distilled to target problematic behaviors, such as invalid patches and insertion pattern propagation. Raw data is first collected from model outputs, then filtered to specific problematic examples, then repaired and filtered for quality before being used in training.

After folding this data into both SFT and RL, we did not notice a significant impact on model behavior. We then hypothesized that the positive examples and corrected negative examples did not have the same distribution or value for model learning, so we upweighted the negative examples during RL.

After doing so, we inspected model rollouts during RL training and were surprised to see that the RL grader was not reliably flagging insertion pattern propagation errors of this type despite the sufficient data representation. Because of the multiple objectives in the already complex grader, to avoid destabilizing the existing grader behavior, we developed a new technique for the RL grader that introduced a new auxiliary grader to specifically address the insertion pattern-following deficit in the primary grader. We gated this grader to examples that had insertions in the ground truth or prediction.

Altogether, the targeted examples, hard example upweighting, and grader changes ultimately corrected the models’ problematic insertion behavior, resulting in the v3 models. This combination of data representation, data balancing, and grader augmentation was a very important learning for us, and a technique we would reuse again when developing the 3-in-1 model.

The Qualitative Must-Haves benchmark

The challenges we faced with the insertion pattern propagation issue, which surfaced only through dogfooding and not through flighting nor through offline evaluation, led us to think about the potential gaps in our existing evaluation methodology. This prompted us to develop a fifth offline evaluation benchmark, Qualitative Must-Haves (QMH), which is a living curated collection of scenarios that previous and current models have found challenging, often discovered through dogfooding.

The objective of this benchmark is distinct from the others. While the others are larger-scale and quantitative, we deliberately kept this one lean and small so that it could serve as a “canary” set to flag issues with models and filter out or rule in model candidates quickly. In addition, it focuses more on preventing past bad behaviors than generically measuring model quality. The name is somewhat of a misnomer, though, as it eventually became quantitative as we developed LLM judges that could serve as human proxies for judging the results.

Both our 2-in-1 and 3-in-1 modeling efforts have greatly benefited from this benchmark as a heuristic for model regressions and potential user frustration, as well as the quick iteration it has enabled due to its small size. We also further included scenarios we added to the QMH dataset in the larger-scale human evaluations that we do at scale.

One of our greatest learnings in developing this benchmark has been that because the models we train have shared data and training pipelines, problematic behaviors can crop up again in future models if not carefully monitored, especially if future models have different objectives, such as adding a new feature. Having a small set of samples that measure critical behaviors that can quickly flag regressions, or if used proactively, prevent possible regressions, has been a game-changer for model selection. It is worth noting that for this set to be reliable, it must have good coverage, so spending time to curate the examples and making sure they are a fair representation of past and potential regressions has been important.

Another learning to underscore is the importance of dogfooding. Nothing beats trying it out yourself, especially as not everything can be captured perfectly on a quantitative scorecard. Testing the boundaries of the model ourselves as end users provides a unique perspective. As developers of products for developers, we consider this mandatory and an important part of the culture we pride ourselves on in providing high-quality code editing models.

Diagram illustrating the model selection process, showing how evaluation benchmarks, human feedback, dogfooding, and online experimentation are combined to compare and choose candidate models.

Figure 5. Our model selection process was refined to leverage the insights gained in each step to efficiently narrow down model candidates, from early filtering using QMH to extensive offline evaluation to dogfooding to online flighting. All intermediate steps in this process are valuable evaluation signals and can also loop back to inform another round of model training.

Takeaways and learnings

Unifying NES and long-distance edits hinged on reformulating the output as a single diff patch format. This one representation could express every prior task and, critically, chain multiple edits into a multi-patch response, which was the foundation for a low-latency tab-tab-tab flow. A few core lessons stood out:

  1. Bootstrap data when pioneering new scenarios. Multi-patch training data didn’t exist, so we synthesized it from single-edit data using pseudolabels and edit playback, followed by quality filtering. This formed the foundation of the SFT and RL data to start the flywheel of multi-patch model development.
  2. A repeatable recipe emerged for fixing specific failure modes. Targeted examples, hard-example upweighting, and a gated auxiliary grader were critical to refining the model from a good model into a shipping candidate. It fixed issues of invalid patches and insertion-pattern propagation, and became our go-to technique going forward.
  3. Try to close the offline-to-online gap. This drove the Pseudo-Online Evaluation (POE) benchmark and a self-refinement loop to calibrate the grader against model outputs and quality signals, and tightening the offline to online gap led to faster and more confident experimentation.
  4. Bring tried and true lessons and intuition into new territory. In both the data filter and the RL grader, we enforced the guideline that edits must flow logically outward by priority and proximity to the cursor. This arose from our experience in orchestrating a successful experience for inline suggestions in the three-model setup.
  5. Dogfooding can catch what metrics are missing. Issues that were invisible offline and online surfaced only through daily use, motivating the small Qualitative Must-Haves “canary” benchmark to guard against regressions in shared pipelines.

Online results

We flighted 2-in-1 model candidates against the production baseline of the three standalone models (completions, NES, and cursor jump). The final shipping candidate was observed to have no statistically significant regressions in any key metrics (acceptance rate, dismissal rate, shown rate, recurring engagement, and accumulated retained characters). In addition, we saw a decrease of 10% in the time it took for suggestions to be shown to the user, along with a reduction of 61% in output tokens. These were mostly due to the more efficient output and input formats and more streamlined client logic.

Try it out

The unified Inline Suggestions experience is available now for paid GitHub Copilot users in VS Code. Update to the latest version of VS Code, then make sure next edit suggestions are enabled.

Give it a try the next time you are in the editor, whether you’re working on a refactor or writing a new function. We hope you enjoy the tab-tab-tab experience and we’d love to hear your feedback!

In the second part of this blog post, we’ll dive deeper into how we moved to the 3-in-1 model for inline suggestions. Stay tuned!

Acknowledgements

Special thanks to Luciana Abud, Alexandru Dima, Yu Hu, Simona Liao, Shengjie Ma, Elsie Nallipogu, and Nick Trogh for their thoughtful feedback, insights, and contributions to this blog post.

We extend our deepest gratitude to our developer community for the ongoing feedback that pushes us to deliver the best possible experiences with VS Code and GitHub Copilot. Huge thanks to the researchers, engineers, product managers, and designers across GitHub and Microsoft who curated the training data, built the training pipeline, evaluation suites, and serving stack, and to the VS Code and GitHub Copilot teams for smooth model releases.

Happy coding! 💙

Visual Studio Code 1.139 (Insiders)


Follow us on LinkedIn, X, Bluesky, Instagram | Follow Insiders Changelog on X or Bluesky


Last updated: September 16, 2026

Welcome to the 1.139 Insiders release of Visual Studio Code.

These release notes cover the Insiders build of VS Code and continue to evolve as new features are added.

You can still track our progress in the Commit log and our list of Closed issues.

These release notes were generated using GitHub Copilot and might contain inaccuracies.

Happy Coding!


September 15, 2026

September 14, 2026

September 11, 2026


We really appreciate people trying our new features as soon as they are ready, so check back here often and learn what’s new.



Visual Studio Code 1.138 (Insiders)


Follow us on LinkedIn, X, Bluesky, Instagram | Follow Insiders Changelog on X or Bluesky


Last updated: September 8, 2026

Welcome to the 1.138 Insiders release of Visual Studio Code.

These release notes cover the Insiders build of VS Code and continue to evolve as new features are added.

You can still track our progress in the Commit log and our list of Closed issues.

Happy Coding!


September 8, 2026

  • Agent Host sessions and chats provide browser-addressable links, making it easier to reopen or share a specific Agents window session from another app, issue, or terminal output. #334963

  • You can create a new Agent session beside the current one in one step, so you can keep the current work visible while starting another session. #334508

  • When you start an Agent session without a workspace, you can attach issue or pull request context by choosing the repository first. #335064

  • Voice mode has more accurate Agent session awareness, including finding recent sessions, switching between them, and reporting current session status. #334600

September 7, 2026

  • Setting:


    editor.forceFullwidthCharacterWidth


    enables full-width characters to occupy exactly two cells when you use a monospace editor font, improving alignment for CJK text in tables, comments, and other grid-like editor content. #155588

September 5, 2026

  • Agent Host offers the Claude or Codex SDK download action whenever the selected agent needs its SDK, so setup recovery is available outside signed-out account setup. #334675

September 4, 2026

  • Agent Host resolves sandbox defaults consistently with the shared runtime, reducing surprises when the same managed sandbox policy is used across clients. #334275

  • The Agents window workspace picker uses a unified searchable list for local folders, GitHub repositories, Cloud repositories, and remote targets, while keeping remote connection actions available in the Remote entry. #334563

September 3, 2026

  • Agent sessions with merged pull requests can be configured to archive inactive sessions, permanently delete automatically archived sessions after a grace period, and remove safe worktrees, giving users and admins more control over agent-session cleanup. #334352

September 1, 2026

  • Agents chat background image layout preferences are saved separately for light and dark themes, so switching themes preserves each theme’s alignment. #333690

We really appreciate people trying our new features as soon as they are ready, so check back here often and learn what’s new.



Visual Studio Code 1.137 (Insiders)


Screenshot showing the Visual Studio Code Insiders banner.

Follow us on LinkedIn, X, Bluesky, Instagram | Follow Insiders Changelog on X or Bluesky


Last updated: September 2, 2026

Welcome to the 1.137 Insiders release of Visual Studio Code.

These release notes cover the Insiders build of VS Code and continue to evolve as new features are added.

You can still track our progress in the Commit log and our list of Closed issues.

These release notes were generated using GitHub Copilot and might contain inaccuracies.

Happy Coding!


September 2, 2026

September 1, 2026

August 31, 2026

  • MCP: Add Server installs servers into the focused Copilot CLI or agent-host session by default, with Install Server Locally… available for local configuration. #305331: AHP: MCP server configuration

We really appreciate people trying our new features as soon as they are ready, so check back here often and learn what’s new.



Introducing the Agent Host for persistent, portable agent sessions


August 26, 2026 by Rob Lourens, Connor Peet, and Brigit Murtaugh

When you assign work to an agent, it should just continue its work, even when you’re not actively watching. Whether you switch to another agent session, move between the editor and the Agents window, or connect remotely from another machine or the browser, you should be able to monitor and interact with that session.

We’re introducing the Agent Host, a self-contained process that owns agent sessions, and the open Agent Host Protocol (AHP) for connecting hosts and clients. Together, they enable sessions to continue after you close the folder or editor window where they started, stay synchronized across clients, run locally or remotely, and support multiple agent harnesses without losing their distinct capabilities.

In this post, we’ll explain why we built the Agent Host, what it enables in VS Code (and how you can try it), how its architecture works, and how AHP opens that architecture to other clients.

Why we built the Agent Host

In late 2025, we added support for closing a local agent chat and keeping it running in the background. That made it possible to run multiple sessions in parallel or focus on another task while you were in VS Code. The next step was enabling those sessions to continue after you closed the folder where they started and to move across VS Code surfaces.

Aside from supporting long-running sessions, we set out to adopt the GitHub Copilot SDK for the Copilot harness in VS Code. Using the SDK gives Copilot a more consistent harness behavior and functionality across Copilot CLI, the standalone GitHub Copilot app, and other Copilot products.

Bringing these efforts together gave us an opportunity to reevaluate how we run agent harnesses in VS Code. An agent harness assembles context, provides tools, runs the agent loop, and applies changes. Without the Agent Host, VS Code runs the local agent harness in each editor window’s extension host, the process that VS Code uses to run extensions such as GitHub Copilot Chat. The extension host isolates extension code from the core editor, however it also ties the agent runtime to one VS Code window. Closing that window stops the runtime. As a result, each window loads its own agent infrastructure.

Moving session state, harness adapters, and baseline workspace capabilities into a dedicated process changes that boundary. The extension host is no longer in the critical path for baseline agent work, and multiple windows can connect to one host instead of each loading a separate runtime. VS Code still communicates with the host, and tools contributed by a client still route back to that client, but the session itself no longer depends on the specific folder or editor window where it started.

This separation also gives VS Code a common foundation for multiple agent harnesses while preserving what makes each one distinct. Earlier this year, we introduced the Claude Agent using Anthropic’s official harness. Copilot and Claude can retain their own SDKs, agent loops, tools, and provider-specific capabilities, while the Agent Host and AHP give them a consistent session experience in VS Code.

What the Agent Host enables

The Agent Host is enabled in the latest VS Code Stable and Insiders. Because the Agent Host owns the session, you can start working with an agent in an editor window and continue with the same live session in the Agents window. Both surfaces stay synchronized, so you can monitor progress and interact with the session wherever you prefer without creating a copy.

The separation between clients and hosts also enables remote sessions. The Agent Host can run with your workspace on another machine while you connect from the desktop or web to check progress, review changes, and manage sessions. Learn more about remote agent sessions, including setup instructions for SSH, dev tunnels, and the web.

Diagram showing a VS Code client connected to a local Agent Host and remote Agent Hosts over dev tunnels and SSH.

Try this workflow to experience how a session continues after you close its folder and stays in sync across VS Code surfaces:

  1. Open a folder in an editor window, select Copilot from the harness picker, and start an agent session as you normally would.

    Screenshot showing the Copilot harness selected from the editor window harness picker.

  2. While the agent is working, close the folder but keep VS Code running. The active turn continues in the Agent Host even though that folder is no longer open.

    Note: Closing a folder does not quit VS Code. For local sessions, VS Code must remain running because it manages the local Agent Host.

  3. Reopen the folder and return to the session. Its state and progress are still there.

  4. Open the Agents window to monitor the same live session. You can work with it from the editor and Agents window without creating a copy, and updates appear in both.

  5. To try a remote connection, connect the Agents window to a remote Agent Host and start or open a session. Then open insiders.vscode.dev/agents, select the same host, and continue the session from your browser.

    Screenshot showing SSH and Tunnels options in the Remote workspace picker in the Agents window.

How the pieces fit

The Agent Host is a dedicated process that owns sessions. It can run locally as a VS Code utility process or remotely as a standalone server. In either case, it remains active across many editor sessions. Previously, we could rely on direct IPC between the extension host and editor window, but a persistent process that could communicate with multiple versions of VS Code necessitates a standardization in how we talk about agents. The Agent Host Protocol (AHP) is that standardization.

Diagram showing VS Code clients communicating with the Agent Host, which uses SDKs to run different agent harnesses.

When the host runs on the same machine as VS Code, all editor windows and the Agents window connect to the single host process. In AHP terms, those windows are clients and the Agent Host plays the server role. VS Code bundles our own implementation of an Agent Host and our UI is a client, but other applications can implement either side of the same agnostic protocol. Clients can also contribute tools based on their own capabilities.

The Agent Host is designed to support different harnesses. Each harness retains its own agent loop and capabilities, while an adapter translates its events into the common AHP session model. Here are two examples of how this works:

  • The Copilot harness is powered by the GitHub Copilot SDK, which manages its runtime as a child process.
  • The Claude harness loads Anthropic’s Claude Agent SDK. Its adapter maps sessions, tools, permissions, and subagents into AHP while retaining features such as slash commands and hooks.

AHP standardizes the client-facing session, not how an agent reasons, manages context, or calls tools. Learn more about choosing an agent harness in VS Code.

Why an open protocol?

Most agent protocols describe a one-to-one conversation between a client and an agent. AHP solves a different problem: coordinating multiple independent clients around the same long-running agent session. The host owns the authoritative, agent-agnostic state, while connected clients can observe progress, contribute actions, approve tool calls, or cancel work.

AHP is deliberately state-first. Rather than expose harness-specific backend events, the host translates them into durable, display-ready state and ordered Redux-like actions. Clients can optimistically apply an action and reconcile it with the host’s sequenced response, then replay missed actions gracefully on reconnection.

The state is opinionated to reflect which user experience clients should present, and it avoids going into implementation details. For example, while our Agent Host drives changes through local git and GitHub, this is modeled as the generic concept of changesets. Implementations can operate on other representations – for example, in-memory virtual file systems like those used on vscode.dev or by the GitHub Repositories extension.

All protocol functionality is exposed as URI-addressable channels, including sessions, chats, terminals, and changesets. When a client subscribes, it receives a snapshot of the current state followed by an ordered stream of actions. Shared reducers apply those actions consistently, so an editor, the Agents window, and a browser client converge on the same view without each client having to understand the harness’s SDK or session model.

A diagram showing an example of AHP messages broadcast by a host.

While AHP handles these coordination challenges, we also want it to be straightforward to implement. At the coarsest level, clients and hosts choose which channels they implement beyond the basic session and chat channels, and negotiate capabilities for finer-grained control. As we add functionality, it will continue to compose into the protocol – providing richer experiences for setups that expose it without adding burden for new clients and hosts.

Build your own AHP client

Because AHP is open, you can build clients that connect to an Agent Host to monitor session progress, review changes, approve tool calls, and contribute tools based on the client’s capabilities.

To get started, run code agent host (or code-insiders agent host for Insiders) to start a standalone Agent Host on your machine. Then connect to it with one of the AHP client libraries:

See the AHP client library table for current versions and additional clients.

Follow along and share feedback

VS Code’s Agent Host implementation and the AHP specification are under active development, and new capabilities continue to roll out. Follow the Agent Host architecture documentation for current VS Code behavior. To follow AHP’s design or share feedback on the protocol overall, explore the AHP documentation and source repository.

As you run agents through the Agent Host in VS Code, please share your feedback with us in the VS Code repository.

Happy coding! 💙

Your Privacy Choices Opt-Out Icon


Today I will modernize a .NET Framework application to .NET 10 using the GitHub Copilot modernization tooling built-in to Visual Studio.

 

The tooling helps us upgrade applications running on legacy versions of .NET and also migrate them to Azure. Today we’re going to focus on the upgrade portion.

 

And, the tooling will do all the work for us! But it doesn’t do everything at once, and that’s good. It introduces checkpoints into the .NET upgrade process to tell us what it has been up to we can then guide it towards the outcome we want. And at each of those checkpoints it creates a markdown file that we can check in to source control – in other words, a record of both what came out of and what went in to the upgrade process.

The app we’re modernizing

BookCatalog is a simple .NET Framework forms-over-data app. You can list books, add one, edit, delete.

screenshot of the book catalog application

Step 1: Open the sample

Clone the repo and open BookCatalog.sln from shared-legacy-app/.
  1. git clone https://github.com/microsoft/dotnet-modernization-for-beginners.git
  2. Open BookCatalog.sln in Visual Studio 2022+ from the shared-legacy-app in the folder you cloned.

Step 2: Start modernization

In Visual Studio, right-click the project or solution and select Modernize. You can also start from Visual Studio with @Modernize.

Screenshot howing the option to start the modernize agent That opens the GitHub Copilot chat window with a customized modernization agent / experience loaded up. This agent is specifically tuned to go through the process of modernizing applications.

Screenshot of the GitHub Copilot chat experience for the modernization agent

It provides several sample prompts, but you can also tell it what to do in natural language.

But for today, pick the top suggested prompt Upgrade to a newer version of .NET.

The agent will then ask you 2 questions. The first is which target framework to upgrade to – pick .NET 10.

screenshot of the agent asking which .NET target framework to upgrade to

And then the flow mode. Remember when I said the modernization process would stop at checkpoints along the way – well, it’ll only do that if we pick Guided so pick that.

Screenshot of the modernization agent asking the type of flow mode to use

What Guided is going to do is it will pause and let you check its work.

The agent will first assess our project and create a report. The guided mode allows us to review that report and make any changes to it. And … we can check that report in to source control. (It looks good – show it to your boss you’ll look super productive! 😉)

Then it will create a plan to fix any issues and do the upgrade. Guided mode lets us review and update that plan should we want to. Guided mode shows us a step-by-step execution of the upgrade itself. You get the picture.

Step 3: Review the assessment

The first thing it rolls through is the assessment. The assessment helps separate blockers, warnings, and informational findings before the upgrade itself starts to run.

Screenshot of reviewing the assessment

The assessment helps you understand what must change first. In this sample, the modernization work includes moving from System.Web.Mvc patterns toward ASP.NET Core equivalents and moving the data layer from Entity Framework 6 to EF Core.

Screenshot of the way to approve the assessment and continue

Step 4: Review the upgrade plan

Once you approve the assessment, the agent will start to create a plan on how it will do the upgrade and it’ll present you with some options on how it can do it.

Screenshot of the upgrade options window for modernization

We could modify the options of how the agent creates the upgrade plan, but we’ll take the default.

screenshot of accepting the default options for upgrading.

Then it produces the plan. It’s a good idea to read that through. This forms the basis of how the agent will upgrade the app.

Screenshot of the upgrade plan

Step 5: Upgrade!

Approve the plan and the agent starts working through the tasks one at a time.

screenshot of approving the plan in the github copilot chat window   Guided mode will pause between the tasks so you can check on its work.

Screenshot of ugided mode in copilot stopping to ask questions during the upgrade   Five tasks later, it’s done!

Screenshot of GitHub Copilot reporting the upgrade process is finished

Verify it

Screenshot of the newly upgraded application running

F5 the application and it should start up. Now, of course AI did the work. And it may not have worked the first time through. You never get the same thing twice with AI. In that case, use Visual Studio’s GitHub Copilot debugging features and you should get it up and running very quickly.

And once the app does start up… it looks exactly the same! The modernization agent doesn’t upgrade the UX for you – that’s for you to vibe on your own.

Wrap-up

The app is upgraded to .NET 10. If you want you can use the GitHub Copilot modernization for .NET tooling to migrate it to Azure too.

We’ve created a course : .NET Modernization for Beginners that goes more in-depth into both the upgrade and migration flows. Check it out. And of course, leave some comments on this post to let us know your experiences.

Visual Studio Code 1.134 (Insiders)


Follow us on LinkedIn, X, Bluesky | Follow Insiders Changelog on X or Bluesky


Last updated: August 11, 2026

Welcome to the 1.134 Insiders release of Visual Studio Code.

These release notes cover the Insiders build of VS Code and continue to evolve as new features are added.

You can still track our progress in the Commit log and our list of Closed issues.

Happy Coding!


August 11, 2026

  • Hide the Voice Mode listening or barge-in placeholder in the chat input while you’re typing, and restore it once the input is cleared. #330288

  • Add a link to configure voice.md instructions to the Voice Mode onboarding banner, alongside the existing settings link. #328083

  • Fixed an issue where Voice Mode instructions in voice.md were not applied. #328860

August 10, 2026

  • Add support for associating HTML files with the integrated browser using the


    workbench.editor.associations


    setting, so they open directly in the browser instead of the text editor. #328545

  • Add subtitles and status indicators to the Chats picker in the Agents window, grouping regular, forked, and side chats separately from active subagents. #329176

  • Add support for selecting the unsaved editors count badge in the Open Editors view to jump to the first unsaved editor. #328907

  • Add a keybinding to reopen the most recently closed chat or session, mirroring how browsers reopen a closed tab. #329184

August 7, 2026

  • Add support for running Codex sessions in the agent host with an OpenAI, ChatGPT, or other configured model provider without requiring GitHub Copilot sign-in. #329668

We really appreciate people trying our new features as soon as they are ready, so check back here often and learn what’s new.