From e9845adbfdc882cec074feed9365f55c1f240fa2 Mon Sep 17 00:00:00 2001 From: Julia Kasper Date: Mon, 4 May 2026 18:05:29 -0700 Subject: [PATCH 1/4] Add blog post: The Coding Harness Behind GitHub Copilot in VS Code --- .gitattributes | 1 + .../agent-harnesses-github-copilot-vscode.md | 92 ++++++++++++++++++ blogs/2026/05/01/agent-harnesses-social.webp | Bin 0 -> 60562 bytes blogs/2026/05/01/agentloop.png | 3 + blogs/2026/05/01/harness.png | 3 + blogs/2026/05/01/modelproviders.png | 3 + 6 files changed, 102 insertions(+) create mode 100644 blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md create mode 100644 blogs/2026/05/01/agent-harnesses-social.webp create mode 100644 blogs/2026/05/01/agentloop.png create mode 100644 blogs/2026/05/01/harness.png create mode 100644 blogs/2026/05/01/modelproviders.png diff --git a/.gitattributes b/.gitattributes index d78ba82f31..c2b9ce40ce 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,3 +9,4 @@ docs/** -linguist-documentation *.md linguist-detectable /workspaces/vscode-docs/docs/copilot/images/overview/configure-completions.png filter=lfs diff=lfs merge=lfs -text /workspaces/vscode-docs/docs/copilot/images/overview/change-completions-model.png filter=lfs diff=lfs merge=lfs -text +blogs/2026/05/01/*.png filter=lfs diff=lfs merge=lfs -text diff --git a/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md b/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md new file mode 100644 index 0000000000..6c6cf28c6c --- /dev/null +++ b/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md @@ -0,0 +1,92 @@ +--- +Order: 130 +TOCTitle: Coding Harness +PageTitle: "The Coding Harness Behind GitHub Copilot in VS Code" +MetaDescription: Learn why the coding harness around GitHub Copilot in VS Code matters as models, tools, agents, and providers evolve. +MetaSocialImage: agent-harnesses-social.webp +Date: 2026-05-01 +Author: VS Code Team +--- + +# The Coding Harness Behind GitHub Copilot in VS Code + +May 7, 2026 by VS Code Team, [@code](https://x.com/code) + +Every few months, a new model drops and the conversation resets. Which one is smartest? Which one is fastest? Which one should we ship? Those are useful questions, but for a product like Visual Studio Code they are incomplete. A model is only one part of the experience. What developers actually feel is the coding harness: the layer that assembles context, exposes tools, runs the agent loop, interprets tool calls, and turns a model's output into something useful inside the editor. + +![Diagram showing that an agent is made up of a model plus a harness. The harness includes the agent loop, tools, context management, and system prompt.](harness.png) + +## What We Mean by the Coding Harness + +That distinction matters because language models do not edit files, execute commands, or run tests by themselves. They produce text. The harness is the system that turns that text into action and feeds the results back so the model can decide what to do next. + +In VS Code, the coding harness has three main responsibilities: + +1. **Context assembly**: Before any request reaches the model, the harness builds a prompt. That prompt includes a system message with behavioral instructions, the user's query, workspace structure (languages, frameworks, open editors), conversation history from prior turns, tool results, custom instructions, and memory from earlier sessions. The harness decides what the model sees, and those decisions directly affect quality. + +2. **Tool exposure**: The harness declares the tools the model is allowed to call: reading files (`read_file`), editing code (`replace_string_in_file` or `apply_patch`), running terminal commands (`run_in_terminal`), searching the codebase (`semantic_search`), and many more. Each tool has a JSON schema the model must follow and a description the model uses to decide when to invoke it. The set of available tools can change per request — some tools are only enabled for certain models, some require user confirmation before execution, users can toggle tools on and off in the tool picker, MCP servers and extensions can contribute entirely new tools that slot into the same loop, and custom agents (`.agent.md`) can restrict their tool set to a specific subset. + +3. **Tool execution**: When the model responds with a tool call instead of text, the harness validates the arguments, runs the tool, handles errors, formats the result, and feeds it back in the next iteration. If the model asks to edit a file, the harness is what actually writes the diff. If it asks to run a command, the harness is what spawns the process, captures output, and relays it. The model only produces JSON like `{"name": "run_in_terminal", "arguments": {"command": "npm test"}}`. + +None of this is the model. All of it shapes what the model can accomplish. + +The piece that ties these together — deciding when to loop, when to stop, and how to keep the conversation coherent across many rounds — is the **agent loop**. + +> The LLM is the reasoning engine. The coding harness is the execution environment around it. The agent loop is the control loop that keeps them working together until the task is done. + +## The Agent Loop + +The core of agent mode in VS Code is a tool-calling loop — a "think → act → observe → think again" cycle. On each iteration, the harness builds the prompt (system instructions + context + history + all tool results so far), sends it to the model, and checks the response. If the model returns text, the turn is done. If it returns tool calls, the harness executes them, records the results, and loops back. + +![Diagram of the agent loop showing the cycle: build prompt, send to model, check response type, execute tools, record results, and loop back.](agentloop.png) + +Each pass through this loop is called a **round**. A single user message might trigger dozens of rounds as the model reads and searches files, edits code, runs tests, reads the output, and iterates on failures. + +The loop is not unbounded. The harness enforces a tool-call limit, checks for cancellation between rounds, and runs stop hooks — extension points that can inspect the model's state and either allow it to finish or push it to keep working ("you were about to stop, but the tests still fail"). + +Within the loop, the prompt is rebuilt on every iteration. That means the model always sees the latest state of the workspace: if it edited a file three rounds ago, the current prompt reflects that edit. The harness also manages conversation summarization — when the accumulated history grows too large, it compresses earlier rounds into a summary so the model can keep working without hitting the context window ceiling. + +### Why the Loop Matters + +A naive implementation would call the model once and apply whatever it says. The loop is what makes multi-step reasoning possible. It lets the agent: + +- **Explore before acting.** Read a file, check its structure, then decide how to edit it. +- **Verify its own work.** Run a command, read the output, fix what went wrong. +- **Decompose complex tasks.** Break a large change into file-by-file edits, testing after each one. +- **Recover from mistakes.** If an edit introduces a type error, the harness surfaces diagnostics and the model can try again. + +This is also why the same model can perform differently across products. The model is one variable. The harness is the other. Each model has different strengths, and we work closely with model providers before each release to optimize our harness - adapting the system prompt, tool descriptions, and loop behavior for each model. + +## The Harness Is Our Product + +When a new model ships, it slots into an existing harness. The system prompt, the tool definitions, the loop logic, the context assembly — all of it was built and tuned over many months of real-world use. The model gets better at filling in the blanks, but the harness defines what the blanks are. + +This matters more now that coding experiences span providers. GitHub Copilot in VS Code supports a growing model ecosystem — developers can switch between models, use auto-selection, bring their own keys, or install provider extensions. The editor deals with a moving ecosystem, not a single stable API. + +The harness is what lets us embrace that choice without forcing developers to relearn the product every time. You should be able to switch models or try a new provider while keeping the core experience familiar: chat, sessions, tools, terminal output, debugging, and source control. + +But integrating a model is rarely just adding an option to a picker. Providers differ in how they expose tool calling, structured outputs, streaming, reasoning controls, prompt caching, context limits, and error behavior. Some models are better at long planning. Some are better at terse edits. Some need different defaults for thinking effort. Each model has different strengths, and we work closely with model providers before each release to adapt the system prompt, tool descriptions, and loop behavior accordingly. + +![Diagram of the partnerhip with model providers](modelproviders.png) + +Different models need different harness behavior. Claude models use `replace_string_in_file` for edits; GPT models use `apply_patch`. Gemini needs reminders to use tool-calling instead of narrating it, and breaks on orphaned tool calls in history. Some models support extended thinking and need reasoning-effort controls. Some work best with a concise system prompt; others need verbose, structured instructions to stay on track. The harness selects different system prompts per model - Claude Sonnet 4 gets a different prompt than Claude 4.5, which gets a different one than Opus. + +These aren't abstract differences — they translate into per-model system prompts, per-model tool sets, per-model streaming behavior, and per-model conversation management. The harness maintains a prompt registry where each model family resolves its own system prompt, reminder instructions, safety rules, and even the XML tag name used to wrap user queries. When a model ships, we don't just flip a switch. We validate tool schemas, adjust context and compaction defaults, check streaming and error behavior, retune reasoning defaults, and re-run agent sessions end to end. + +## Evaluation keeps the harness honest + +Evaluation is what keeps this from turning into guesswork. Public benchmarks are important because they give the community a shared external reference point. [SWE-bench](https://www.swebench.com/) measures whether systems can resolve real GitHub issues in live repositories. SWE-bench Verified tightened that evaluation by filtering out underspecified or unfair tasks. Terminal-focused benchmarks add a different kind of pressure: realistic command-line tasks, unique environments, and verification tests that require the agent to operate reliably outside a single file edit. + +Those benchmarks tell us whether a model and agent system is strong in ways the broader community recognizes. They also influence product work. Improvements to VS Code's agent mode have come from evaluation runs that changed prompts, tool descriptions, and tool design, including work we discussed when sharing agent performance on SWE-bench Verified. + +But public benchmarks are not enough. They cannot tell us whether a model works well inside the VS Code harness, with our prompts, our context policies, our approval flows, our editor interactions, and our expectations around iteration speed and reliability. That is why we also rely on product-specific evaluation: tasks that exercise the actual VS Code agent experience, not just the model in isolation. + +This combination matches the reality of shipping AI products. Frontier evals help us move with the model ecosystem. Contextual evals help us ship confidently in our own product. Together they let us do something more useful than chase leaderboard numbers: they help us decide when a model is actually good enough for the experience we want developers to have in VS Code. + +## What this means in VS Code + +The model still matters. So do the tools. But as agents become part of everyday development, the harness is what turns model capability into a workflow you can use, review, and trust. + +Open Chat in VS Code and use the agent or session target picker to choose how you want Copilot to work: local Agent for interactive implementation, Plan when you want a structured approach first, Ask when you want answers without file changes and Copilot CLI for background work. + +To go deeper, start with the [agents overview](https://code.visualstudio.com/docs/copilot/agents/overview) and try moving one task through more than one harness. The differences become clear quickly, and so does the value of having them all inside VS Code. \ No newline at end of file diff --git a/blogs/2026/05/01/agent-harnesses-social.webp b/blogs/2026/05/01/agent-harnesses-social.webp new file mode 100644 index 0000000000000000000000000000000000000000..4660ee54a7e7b8abfa929792108f69ee44589808 GIT binary patch literal 60562 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 L@11X(5D@ Date: Tue, 5 May 2026 18:58:33 -0700 Subject: [PATCH 2/4] Update blog post and replace images --- .../agent-harnesses-github-copilot-vscode.md | 66 ++++++++++++------- blogs/2026/05/01/agent_model_harness.png | 3 + blogs/2026/05/01/benchmark.png | 3 + blogs/2026/05/01/evaluations.png | 3 + blogs/2026/05/01/harness.png | 3 - blogs/2026/05/01/model_provider_loop.png | 3 + blogs/2026/05/01/modelproviders.png | 3 - 7 files changed, 53 insertions(+), 31 deletions(-) create mode 100644 blogs/2026/05/01/agent_model_harness.png create mode 100644 blogs/2026/05/01/benchmark.png create mode 100644 blogs/2026/05/01/evaluations.png delete mode 100644 blogs/2026/05/01/harness.png create mode 100644 blogs/2026/05/01/model_provider_loop.png delete mode 100644 blogs/2026/05/01/modelproviders.png diff --git a/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md b/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md index 6c6cf28c6c..a640ef05fc 100644 --- a/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md +++ b/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md @@ -4,17 +4,17 @@ TOCTitle: Coding Harness PageTitle: "The Coding Harness Behind GitHub Copilot in VS Code" MetaDescription: Learn why the coding harness around GitHub Copilot in VS Code matters as models, tools, agents, and providers evolve. MetaSocialImage: agent-harnesses-social.webp -Date: 2026-05-01 +Date: 2026-05-07 Author: VS Code Team --- # The Coding Harness Behind GitHub Copilot in VS Code -May 7, 2026 by VS Code Team, [@code](https://x.com/code) +May 7, 2026 by [Julia Kasper](https://github.com/jukasper) Every few months, a new model drops and the conversation resets. Which one is smartest? Which one is fastest? Which one should we ship? Those are useful questions, but for a product like Visual Studio Code they are incomplete. A model is only one part of the experience. What developers actually feel is the coding harness: the layer that assembles context, exposes tools, runs the agent loop, interprets tool calls, and turns a model's output into something useful inside the editor. -![Diagram showing that an agent is made up of a model plus a harness. The harness includes the agent loop, tools, context management, and system prompt.](harness.png) +![Diagram showing that an agent is made up of a model plus a harness. The harness includes the agent loop, tools, context management, and system prompt.](agent_model_harness.png) ## What We Mean by the Coding Harness @@ -24,27 +24,25 @@ In VS Code, the coding harness has three main responsibilities: 1. **Context assembly**: Before any request reaches the model, the harness builds a prompt. That prompt includes a system message with behavioral instructions, the user's query, workspace structure (languages, frameworks, open editors), conversation history from prior turns, tool results, custom instructions, and memory from earlier sessions. The harness decides what the model sees, and those decisions directly affect quality. -2. **Tool exposure**: The harness declares the tools the model is allowed to call: reading files (`read_file`), editing code (`replace_string_in_file` or `apply_patch`), running terminal commands (`run_in_terminal`), searching the codebase (`semantic_search`), and many more. Each tool has a JSON schema the model must follow and a description the model uses to decide when to invoke it. The set of available tools can change per request — some tools are only enabled for certain models, some require user confirmation before execution, users can toggle tools on and off in the tool picker, MCP servers and extensions can contribute entirely new tools that slot into the same loop, and custom agents (`.agent.md`) can restrict their tool set to a specific subset. +2. **Tool exposure**: The harness declares the tools the model is allowed to call: reading files (`read_file`), editing code (`replace_string_in_file` or `apply_patch`), running terminal commands (`run_in_terminal`), searching the codebase (`semantic_search`), and many more. Each tool has a JSON schema the model must follow and a description the model uses to decide when to invoke it. The set of available tools can change per request. Some tools are only enabled for certain models, some require user confirmation before execution, users can toggle tools on and off in the tool picker, MCP servers and extensions can contribute entirely new tools that slot into the same loop, and custom agents (`.agent.md`) can restrict their tool set to a specific subset. 3. **Tool execution**: When the model responds with a tool call instead of text, the harness validates the arguments, runs the tool, handles errors, formats the result, and feeds it back in the next iteration. If the model asks to edit a file, the harness is what actually writes the diff. If it asks to run a command, the harness is what spawns the process, captures output, and relays it. The model only produces JSON like `{"name": "run_in_terminal", "arguments": {"command": "npm test"}}`. None of this is the model. All of it shapes what the model can accomplish. -The piece that ties these together — deciding when to loop, when to stop, and how to keep the conversation coherent across many rounds — is the **agent loop**. - -> The LLM is the reasoning engine. The coding harness is the execution environment around it. The agent loop is the control loop that keeps them working together until the task is done. +The piece that ties these together, deciding when to loop, when to stop, and how to keep the conversation coherent across many rounds, is the **agent loop**. ## The Agent Loop -The core of agent mode in VS Code is a tool-calling loop — a "think → act → observe → think again" cycle. On each iteration, the harness builds the prompt (system instructions + context + history + all tool results so far), sends it to the model, and checks the response. If the model returns text, the turn is done. If it returns tool calls, the harness executes them, records the results, and loops back. +The core of agent mode in VS Code is a tool-calling loop, a "think → act → observe → think again" cycle. On each iteration, the harness builds the prompt (system instructions + context + history + all tool results so far), sends it to the model, and checks the response. If the model returns text, the turn is done. If it returns tool calls, the harness executes them, records the results, and loops back. ![Diagram of the agent loop showing the cycle: build prompt, send to model, check response type, execute tools, record results, and loop back.](agentloop.png) -Each pass through this loop is called a **round**. A single user message might trigger dozens of rounds as the model reads and searches files, edits code, runs tests, reads the output, and iterates on failures. +Each pass through this loop is called a round. A single user message might trigger dozens of rounds as the model reads and searches files, edits code, runs tests, reads the output, and iterates on failures. -The loop is not unbounded. The harness enforces a tool-call limit, checks for cancellation between rounds, and runs stop hooks — extension points that can inspect the model's state and either allow it to finish or push it to keep working ("you were about to stop, but the tests still fail"). +The loop is not unbounded. The harness enforces a tool-call limit, checks for cancellation between rounds, and runs stop hooks, extension points that can inspect the model's state and either allow it to finish or push it to keep working ("you were about to stop, but the tests still fail"). -Within the loop, the prompt is rebuilt on every iteration. That means the model always sees the latest state of the workspace: if it edited a file three rounds ago, the current prompt reflects that edit. The harness also manages conversation summarization — when the accumulated history grows too large, it compresses earlier rounds into a summary so the model can keep working without hitting the context window ceiling. +Within the loop, the prompt is rebuilt on every iteration. That means the model always sees the latest state of the workspace: if it edited a file three rounds ago, the current prompt reflects that edit. The harness also manages conversation summarization. When the accumulated history grows too large, it compresses earlier rounds into a summary so the model can keep working without hitting the context window ceiling. ### Why the Loop Matters @@ -55,38 +53,56 @@ A naive implementation would call the model once and apply whatever it says. The - **Decompose complex tasks.** Break a large change into file-by-file edits, testing after each one. - **Recover from mistakes.** If an edit introduces a type error, the harness surfaces diagnostics and the model can try again. -This is also why the same model can perform differently across products. The model is one variable. The harness is the other. Each model has different strengths, and we work closely with model providers before each release to optimize our harness - adapting the system prompt, tool descriptions, and loop behavior for each model. +This is also why the same model can perform differently across products. The model is one variable. The harness is the other. ## The Harness Is Our Product -When a new model ships, it slots into an existing harness. The system prompt, the tool definitions, the loop logic, the context assembly — all of it was built and tuned over many months of real-world use. The model gets better at filling in the blanks, but the harness defines what the blanks are. +When a new model ships, it needs to fit into an existing harness. The system prompt, the tool definitions, the loop logic, the context assembly, all of it was built and tuned over many months of real-world use. The model gets better at filling in the blanks, but the harness defines what the blanks are. -This matters more now that coding experiences span providers. GitHub Copilot in VS Code supports a growing model ecosystem — developers can switch between models, use auto-selection, bring their own keys, or install provider extensions. The editor deals with a moving ecosystem, not a single stable API. +This matters even more because GitHub Copilot spans model providers. GitHub Copilot in VS Code supports a growing model ecosystem. Developers can switch between models, use auto-selection, bring their own keys, or install provider extensions. The editor deals with a moving ecosystem, not a single stable API. The harness is what lets us embrace that choice without forcing developers to relearn the product every time. You should be able to switch models or try a new provider while keeping the core experience familiar: chat, sessions, tools, terminal output, debugging, and source control. -But integrating a model is rarely just adding an option to a picker. Providers differ in how they expose tool calling, structured outputs, streaming, reasoning controls, prompt caching, context limits, and error behavior. Some models are better at long planning. Some are better at terse edits. Some need different defaults for thinking effort. Each model has different strengths, and we work closely with model providers before each release to adapt the system prompt, tool descriptions, and loop behavior accordingly. +But integrating a model is rarely just adding an option to a picker. Providers differ in how they expose tool calling, structured outputs, streaming, reasoning controls, prompt caching, context limits, and error behavior. Some models are better at long planning. Some are better at terse edits. Each model has different strengths, and we work closely with model providers before each release to adapt the system prompt, tool descriptions, and loop behavior accordingly. -![Diagram of the partnerhip with model providers](modelproviders.png) +![Diagram of the partnership between VS Code and model providers.](model_provider_loop.png) Different models need different harness behavior. Claude models use `replace_string_in_file` for edits; GPT models use `apply_patch`. Gemini needs reminders to use tool-calling instead of narrating it, and breaks on orphaned tool calls in history. Some models support extended thinking and need reasoning-effort controls. Some work best with a concise system prompt; others need verbose, structured instructions to stay on track. The harness selects different system prompts per model - Claude Sonnet 4 gets a different prompt than Claude 4.5, which gets a different one than Opus. -These aren't abstract differences — they translate into per-model system prompts, per-model tool sets, per-model streaming behavior, and per-model conversation management. The harness maintains a prompt registry where each model family resolves its own system prompt, reminder instructions, safety rules, and even the XML tag name used to wrap user queries. When a model ships, we don't just flip a switch. We validate tool schemas, adjust context and compaction defaults, check streaming and error behavior, retune reasoning defaults, and re-run agent sessions end to end. +These aren't abstract differences. They translate into per-model system prompts, per-model tool sets, and per-model conversation management. When a new model ships, we don't just flip a switch. We validate tool schemas, retune defaults, and re-run full agent sessions before anything ships. The harder question is how we know those changes actually made things better. ## Evaluation keeps the harness honest -Evaluation is what keeps this from turning into guesswork. Public benchmarks are important because they give the community a shared external reference point. [SWE-bench](https://www.swebench.com/) measures whether systems can resolve real GitHub issues in live repositories. SWE-bench Verified tightened that evaluation by filtering out underspecified or unfair tasks. Terminal-focused benchmarks add a different kind of pressure: realistic command-line tasks, unique environments, and verification tests that require the agent to operate reliably outside a single file edit. +That's where evaluation comes in. Before a model ships in VS Code, we evaluate it from multiple angles. We run offline benchmarks, test it internally, and compare it against the models already available in the product. After launch, we keep measuring: A/B tests, aggregate usage signals, and weekly reporting help us understand how the model behaves in real developer workflows. + + +![Diagram showing an overview of the VS Code evaluation pipeline.](evaluations.png) + +Public benchmarks are useful as shared reference points. We use them to compare against the broader model ecosystem and to catch obvious regressions. But at frontier levels, they are no longer enough on their own. + +Part of the issue is coverage. SWE-bench is valuable, but it is still centered on public bug-fixing tasks. Terminal-Bench is useful for measuring command-line competence, but many tasks look more like isolated terminal puzzles than the kinds of workflows developers actually bring to an editor. Real coding agents need to do more than patch a known bug or solve a shell challenge. They need to scaffold projects, migrate codebases, refactor across files, follow instructions, and handle terminals and browsers. + +Grading is another limitation. Many public benchmarks assume a narrow target solution: one expected patch, one expected command sequence, or one expected final answer. That can penalize valid approaches that solve the user’s problem differently. And contamination is becoming harder to ignore. SWE-bench tasks come from public repositories that may appear in training data, which makes leaderboard scores harder to interpret. OpenAI [stopped reporting SWE-bench Verified results](https://openai.com/index/why-we-no-longer-evaluate-swe-bench-verified/) after finding that frontier models could sometimes reproduce gold patches from memory. + +We still run these benchmarks. They are useful regression tests. But when we decide which models are ready to ship in VS Code, we need something closer to the product we are actually building. + +### Building VSC-Bench + +That's why we built VSC-Bench, our offline evaluation suite for VS Code agent behavior. VSC-Bench focuses on VS Code-specific developer tasks that public benchmarks do not cover well: custom agent modes, extension workflows, MCP and tool use, terminal and browser interaction, multi-turn conversations, and multi-language coding tasks across TypeScript, Python, C++, and others. + +For example, one task asks the agent to scaffold a new API endpoint, write a test, run it, and fix any failures. The assertions check that the route exists, the test passes, and that the agent used the terminal to verify its work rather than just writing code and stopping. + +Each VSC-Bench task runs in a reproducible, containerized workspace. The harness launches VS Code, opens the workspace, sends one or more user prompts to the agent, lets the agent respond with text and tool calls, and then evaluates what happened. That gives us a more realistic view of the full agent loop: not just whether the final code looks right, but whether the agent used the editor, terminal, language services, browser, and tools in ways that match the VS Code experience. -Those benchmarks tell us whether a model and agent system is strong in ways the broader community recognizes. They also influence product work. Improvements to VS Code's agent mode have come from evaluation runs that changed prompts, tool descriptions, and tool design, including work we discussed when sharing agent performance on SWE-bench Verified. +Each task carries its own assertions: checks on the final workspace (did the project build, did the tests pass) and checks on agent behavior (did it use the right tools, respect instructions, avoid unnecessary edits). For subjective criteria, we use model-based grading. The result is a benchmark signal backed by inspectable artifacts: patches, logs, screenshots, and trajectories. We refresh the suite as VS Code and agent usage evolve, ranging from small sanity checks to harder, multi-step workflows that stress planning, context management, and tool choice. Together with public benchmarks, VSC-Bench gives us a more balanced signal: public evals tell us how a model compares to the field, while product-specific evals tell us whether it is ready for the experience developers expect inside VS Code. -But public benchmarks are not enough. They cannot tell us whether a model works well inside the VS Code harness, with our prompts, our context policies, our approval flows, our editor interactions, and our expectations around iteration speed and reliability. That is why we also rely on product-specific evaluation: tasks that exercise the actual VS Code agent experience, not just the model in isolation. -This combination matches the reality of shipping AI products. Frontier evals help us move with the model ecosystem. Contextual evals help us ship confidently in our own product. Together they let us do something more useful than chase leaderboard numbers: they help us decide when a model is actually good enough for the experience we want developers to have in VS Code. +## The Model Is the Engine. The Harness Is the Car. -## What this means in VS Code +We started with a question developers ask every few months: which model is best? The answer we keep arriving at is: it's not just the model. It's the context it sees, the tools it can reach, the loop that keeps it going, and the evaluation that makes sure it all works. That's the harness, and it's what we spend most of our engineering time on. -The model still matters. So do the tools. But as agents become part of everyday development, the harness is what turns model capability into a workflow you can use, review, and trust. +As models gain new capabilities like longer context, better planning, and native tool use, the harness evolves to take advantage of them. And as developers push agent mode into new workflows, we feed what we learn back into the loop, the tools, and the evaluations. Every VS Code release ships harness improvements alongside model updates. -Open Chat in VS Code and use the agent or session target picker to choose how you want Copilot to work: local Agent for interactive implementation, Plan when you want a structured approach first, Ask when you want answers without file changes and Copilot CLI for background work. +You can already extend the harness yourself with [custom instructions](https://code.visualstudio.com/docs/copilot/copilot-customization), [custom agents](https://code.visualstudio.com/docs/copilot/copilot-customization#_custom-agents), and [MCP servers](https://code.visualstudio.com/docs/copilot/chat/mcp-servers). Try switching models, add your own tools, and let us know what works — share your feedback in [our GitHub repo](https://github.com/microsoft/vscode). -To go deeper, start with the [agents overview](https://code.visualstudio.com/docs/copilot/agents/overview) and try moving one task through more than one harness. The differences become clear quickly, and so does the value of having them all inside VS Code. \ No newline at end of file +Happy coding! 💙 \ No newline at end of file diff --git a/blogs/2026/05/01/agent_model_harness.png b/blogs/2026/05/01/agent_model_harness.png new file mode 100644 index 0000000000..1e9a0be401 --- /dev/null +++ b/blogs/2026/05/01/agent_model_harness.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60efa287b4aa9e669f4f997a6053a0973adf33bb603cf51ff8c60d3cc7239c01 +size 87681 diff --git a/blogs/2026/05/01/benchmark.png b/blogs/2026/05/01/benchmark.png new file mode 100644 index 0000000000..1257f12db2 --- /dev/null +++ b/blogs/2026/05/01/benchmark.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76c227bf6dfeeaa836fe15858be615aaf255854415a704de605899b0d774a1bc +size 192102 diff --git a/blogs/2026/05/01/evaluations.png b/blogs/2026/05/01/evaluations.png new file mode 100644 index 0000000000..6ed72a6ed7 --- /dev/null +++ b/blogs/2026/05/01/evaluations.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:06fa3d3de1800c1191e013041b7df77418f6e02555bf21aaa5b66f099892088f +size 192487 diff --git a/blogs/2026/05/01/harness.png b/blogs/2026/05/01/harness.png deleted file mode 100644 index 333f70508b..0000000000 --- a/blogs/2026/05/01/harness.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9a522ed1e692e17c0490412d57b0eff10ca9fd8b0e15d9c64637d19a37c380f8 -size 57099 diff --git a/blogs/2026/05/01/model_provider_loop.png b/blogs/2026/05/01/model_provider_loop.png new file mode 100644 index 0000000000..5b94c17ab3 --- /dev/null +++ b/blogs/2026/05/01/model_provider_loop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2c53ad860ebb4ee120e316991a143ffebe8ebaf8476b66fca9afb54779ac839 +size 345307 diff --git a/blogs/2026/05/01/modelproviders.png b/blogs/2026/05/01/modelproviders.png deleted file mode 100644 index c3cc5fabb3..0000000000 --- a/blogs/2026/05/01/modelproviders.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7413748d82adc59614ae0918e6bd37d3cc6214a2b0e9ecc6813c4975df7610b8 -size 338877 From ecb70a31038215870a48e164bc81a77c00910b18 Mon Sep 17 00:00:00 2001 From: Julia Kasper Date: Thu, 7 May 2026 17:45:15 -0700 Subject: [PATCH 3/4] Address blog review feedback --- .../agent-harnesses-github-copilot-vscode.md | 52 +++++++++++-------- blogs/2026/05/01/agent-loop.png | 3 ++ blogs/2026/05/01/agent_model_harness.png | 4 +- blogs/2026/05/01/evaluations.png | 4 +- blogs/2026/05/01/model_provider_loop.png | 4 +- 5 files changed, 38 insertions(+), 29 deletions(-) create mode 100644 blogs/2026/05/01/agent-loop.png diff --git a/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md b/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md index a640ef05fc..2cb2f2db11 100644 --- a/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md +++ b/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md @@ -12,13 +12,13 @@ Author: VS Code Team May 7, 2026 by [Julia Kasper](https://github.com/jukasper) -Every few months, a new model drops and the conversation resets. Which one is smartest? Which one is fastest? Which one should we ship? Those are useful questions, but for a product like Visual Studio Code they are incomplete. A model is only one part of the experience. What developers actually feel is the coding harness: the layer that assembles context, exposes tools, runs the agent loop, interprets tool calls, and turns a model's output into something useful inside the editor. +With each new model release, the same conversation is reignited. Which model is the smartest? Which one is fastest? Which one should we use? Those are useful questions, but for a product like Visual Studio Code the model is only one part of the agentic coding experience. What developers actually interact with is the coding harness: the layer that assembles context, exposes tools, runs the agent loop, interprets tool calls, and turns a model's output into something useful inside the editor. In this post, we'll look at what that harness does, why it matters, and how we evaluate it as models and developer workflows evolve. ![Diagram showing that an agent is made up of a model plus a harness. The harness includes the agent loop, tools, context management, and system prompt.](agent_model_harness.png) -## What We Mean by the Coding Harness +## What is the coding harness? -That distinction matters because language models do not edit files, execute commands, or run tests by themselves. They produce text. The harness is the system that turns that text into action and feeds the results back so the model can decide what to do next. +Language models do not edit files, execute commands, or run tests by themselves. They can only produce text. The coding harness is the system that acts as a bridge between the code editor and the language model. It turns that text into action and feeds the results back so the model can decide what to do next. In VS Code, the coding harness has three main responsibilities: @@ -26,61 +26,65 @@ In VS Code, the coding harness has three main responsibilities: 2. **Tool exposure**: The harness declares the tools the model is allowed to call: reading files (`read_file`), editing code (`replace_string_in_file` or `apply_patch`), running terminal commands (`run_in_terminal`), searching the codebase (`semantic_search`), and many more. Each tool has a JSON schema the model must follow and a description the model uses to decide when to invoke it. The set of available tools can change per request. Some tools are only enabled for certain models, some require user confirmation before execution, users can toggle tools on and off in the tool picker, MCP servers and extensions can contribute entirely new tools that slot into the same loop, and custom agents (`.agent.md`) can restrict their tool set to a specific subset. -3. **Tool execution**: When the model responds with a tool call instead of text, the harness validates the arguments, runs the tool, handles errors, formats the result, and feeds it back in the next iteration. If the model asks to edit a file, the harness is what actually writes the diff. If it asks to run a command, the harness is what spawns the process, captures output, and relays it. The model only produces JSON like `{"name": "run_in_terminal", "arguments": {"command": "npm test"}}`. +3. **Tool execution**: When the model requests a tool to be run (using JSON like `{"name": "run_in_terminal", "arguments": {"command": "npm test"}}`), the harness is the one that validates the arguments, runs the tool, handles errors, formats the result, and feeds it back in the next iteration. For example, if the model asks to edit a file, the harness writes the diff. If the model asks to run a shell command, the harness is what spawns the process, captures output, and relays it. -None of this is the model. All of it shapes what the model can accomplish. +None of these tasks can be directly achieved by the language model. However, this input determines the behavior and outcome of the model and what you experience in the code editor. -The piece that ties these together, deciding when to loop, when to stop, and how to keep the conversation coherent across many rounds, is the **agent loop**. +The logic that orchestrates these tasks, deciding when to continue or stop iterating and how to keep the conversation coherent across many rounds, is the **agent loop**. -## The Agent Loop +## The agent loop -The core of agent mode in VS Code is a tool-calling loop, a "think → act → observe → think again" cycle. On each iteration, the harness builds the prompt (system instructions + context + history + all tool results so far), sends it to the model, and checks the response. If the model returns text, the turn is done. If it returns tool calls, the harness executes them, records the results, and loops back. +At its core, when you use an agent in VS Code, a tool-calling loop happens: a **"think → act → observe → think again" cycle**. On each iteration, the agent harness builds the prompt (system instructions + context + history + all tool results so far), sends it to the model, and checks the response. -![Diagram of the agent loop showing the cycle: build prompt, send to model, check response type, execute tools, record results, and loop back.](agentloop.png) +If the response includes tool calls, the harness executes those tools, captures their results, and loops back. If there are no tool calls, the loop can finish and the assistant’s text becomes the final response. -Each pass through this loop is called a round. A single user message might trigger dozens of rounds as the model reads and searches files, edits code, runs tests, reads the output, and iterates on failures. +![Simplified diagram of the VS Code agent loop: the user sends a chat message, the tool-calling loop builds a prompt, sends it to the model, executes requested tools, records results, checks loop-control conditions, and either continues or finalizes the chat result.](agent-loop.png) -The loop is not unbounded. The harness enforces a tool-call limit, checks for cancellation between rounds, and runs stop hooks, extension points that can inspect the model's state and either allow it to finish or push it to keep working ("you were about to stop, but the tests still fail"). +A **turn** is the user-visible chat exchange: you send one message, and the agent eventually produces a response. During that turn, the agent loop may perform many **rounds**. A round is one pass through the loop: build the prompt, call the model, receive text and/or tool calls, execute any tools, record the results, and decide whether to continue. The full execution of all those rounds is the loop’s **run**. + +A single user turn might trigger many rounds as the model searches files, reads code, edits files, runs tests, reads the output, and iterates on failures. + +The tool-calling loop is bounded by loop-control checks. We enforce a tool-call limit, checks for cancellation between rounds, and runs stop hooks. Stop hooks are extension points that can inspect the agent state and either allow it to finish or push it to keep working. Within the loop, the prompt is rebuilt on every iteration. That means the model always sees the latest state of the workspace: if it edited a file three rounds ago, the current prompt reflects that edit. The harness also manages conversation summarization. When the accumulated history grows too large, it compresses earlier rounds into a summary so the model can keep working without hitting the context window ceiling. -### Why the Loop Matters +### Why do we need an agent loop? -A naive implementation would call the model once and apply whatever it says. The loop is what makes multi-step reasoning possible. It lets the agent: +A simple implementation would call the model once and apply whatever it says. That can work for simple requests where all the relevant information is already available in the prompt. Most coding tasks are more complex: the agent needs to inspect files, discover project conventions, run commands, see what failed, and adjust based on what it learns. The loop is what makes that kind of multi-step reasoning possible. It lets the agent: - **Explore before acting.** Read a file, check its structure, then decide how to edit it. - **Verify its own work.** Run a command, read the output, fix what went wrong. - **Decompose complex tasks.** Break a large change into file-by-file edits, testing after each one. - **Recover from mistakes.** If an edit introduces a type error, the harness surfaces diagnostics and the model can try again. -This is also why the same model can perform differently across products. The model is one variable. The harness is the other. +This is another reason why the same model can perform differently across products. The model is one variable. The harness is the other. -## The Harness Is Our Product +## The harness is the product When a new model ships, it needs to fit into an existing harness. The system prompt, the tool definitions, the loop logic, the context assembly, all of it was built and tuned over many months of real-world use. The model gets better at filling in the blanks, but the harness defines what the blanks are. -This matters even more because GitHub Copilot spans model providers. GitHub Copilot in VS Code supports a growing model ecosystem. Developers can switch between models, use auto-selection, bring their own keys, or install provider extensions. The editor deals with a moving ecosystem, not a single stable API. +This matters even more because GitHub Copilot spans multiple model providers. GitHub Copilot in VS Code supports a growing model ecosystem. Developers can switch between models, use auto-selection, bring their own keys, or install extra providers via extensions. This means that VS Code has to deal with broad and continuously evolving ecosystem, not a single stable API. The harness is what lets us embrace that choice without forcing developers to relearn the product every time. You should be able to switch models or try a new provider while keeping the core experience familiar: chat, sessions, tools, terminal output, debugging, and source control. But integrating a model is rarely just adding an option to a picker. Providers differ in how they expose tool calling, structured outputs, streaming, reasoning controls, prompt caching, context limits, and error behavior. Some models are better at long planning. Some are better at terse edits. Each model has different strengths, and we work closely with model providers before each release to adapt the system prompt, tool descriptions, and loop behavior accordingly. -![Diagram of the partnership between VS Code and model providers.](model_provider_loop.png) +![Flow diagram showing VS Code and model providers iterating from an upcoming model release through Copilot API onboarding, harness optimization, evaluation, provider feedback, and launch.](model_provider_loop.png) Different models need different harness behavior. Claude models use `replace_string_in_file` for edits; GPT models use `apply_patch`. Gemini needs reminders to use tool-calling instead of narrating it, and breaks on orphaned tool calls in history. Some models support extended thinking and need reasoning-effort controls. Some work best with a concise system prompt; others need verbose, structured instructions to stay on track. The harness selects different system prompts per model - Claude Sonnet 4 gets a different prompt than Claude 4.5, which gets a different one than Opus. -These aren't abstract differences. They translate into per-model system prompts, per-model tool sets, and per-model conversation management. When a new model ships, we don't just flip a switch. We validate tool schemas, retune defaults, and re-run full agent sessions before anything ships. The harder question is how we know those changes actually made things better. +All these per-model differences aren't trivial. They translate into per-model system prompts, per-model tool sets, and per-model conversation management. This means that when a new model ships, we don't just flip a switch but we need to validate its behavior. We validate tool schemas, retune defaults, and re-run full agent sessions before anything ships. The harder question is how we know those changes actually made things better. ## Evaluation keeps the harness honest -That's where evaluation comes in. Before a model ships in VS Code, we evaluate it from multiple angles. We run offline benchmarks, test it internally, and compare it against the models already available in the product. After launch, we keep measuring: A/B tests, aggregate usage signals, and weekly reporting help us understand how the model behaves in real developer workflows. +Just like you need to test a new feature before you ship it, models also need to be tested. That's where model evaluation comes in. Before a model ships in VS Code, we evaluate it from multiple angles. We run offline benchmarks, test it internally, and compare it against the models already available in the product. After the model is live, we keep measuring: A/B tests, aggregate usage signals, and weekly reporting help us understand how the model behaves in real developer workflows. ![Diagram showing an overview of the VS Code evaluation pipeline.](evaluations.png) -Public benchmarks are useful as shared reference points. We use them to compare against the broader model ecosystem and to catch obvious regressions. But at frontier levels, they are no longer enough on their own. +There are multiple public model benchmarks, which are useful as a shared reference point. We use these benchmarks to compare against the broader model ecosystem and to catch obvious regressions. But at frontier levels, they are no longer enough on their own. -Part of the issue is coverage. SWE-bench is valuable, but it is still centered on public bug-fixing tasks. Terminal-Bench is useful for measuring command-line competence, but many tasks look more like isolated terminal puzzles than the kinds of workflows developers actually bring to an editor. Real coding agents need to do more than patch a known bug or solve a shell challenge. They need to scaffold projects, migrate codebases, refactor across files, follow instructions, and handle terminals and browsers. +One of the issues with the public benchmarks is coverage. SWE-bench is valuable, but it is still centered on public bug-fixing tasks. Terminal-Bench is useful for measuring command-line competence, but many tasks look more like isolated terminal puzzles than the kinds of workflows developers actually bring to an editor. Real-world coding agents need to do more than patch a known bug or solve a shell challenge. They need to scaffold projects, migrate codebases, refactor across files, follow instructions, and handle terminals and browsers. Grading is another limitation. Many public benchmarks assume a narrow target solution: one expected patch, one expected command sequence, or one expected final answer. That can penalize valid approaches that solve the user’s problem differently. And contamination is becoming harder to ignore. SWE-bench tasks come from public repositories that may appear in training data, which makes leaderboard scores harder to interpret. OpenAI [stopped reporting SWE-bench Verified results](https://openai.com/index/why-we-no-longer-evaluate-swe-bench-verified/) after finding that frontier models could sometimes reproduce gold patches from memory. @@ -90,6 +94,8 @@ We still run these benchmarks. They are useful regression tests. But when we dec That's why we built VSC-Bench, our offline evaluation suite for VS Code agent behavior. VSC-Bench focuses on VS Code-specific developer tasks that public benchmarks do not cover well: custom agent modes, extension workflows, MCP and tool use, terminal and browser interaction, multi-turn conversations, and multi-language coding tasks across TypeScript, Python, C++, and others. +![Scatter chart comparing VSC-Bench model resolution rate against median total tokens, with each point representing a different model.](vscbench.png) + For example, one task asks the agent to scaffold a new API endpoint, write a test, run it, and fix any failures. The assertions check that the route exists, the test passes, and that the agent used the terminal to verify its work rather than just writing code and stopping. Each VSC-Bench task runs in a reproducible, containerized workspace. The harness launches VS Code, opens the workspace, sends one or more user prompts to the agent, lets the agent respond with text and tool calls, and then evaluates what happened. That gives us a more realistic view of the full agent loop: not just whether the final code looks right, but whether the agent used the editor, terminal, language services, browser, and tools in ways that match the VS Code experience. @@ -97,9 +103,9 @@ Each VSC-Bench task runs in a reproducible, containerized workspace. The harness Each task carries its own assertions: checks on the final workspace (did the project build, did the tests pass) and checks on agent behavior (did it use the right tools, respect instructions, avoid unnecessary edits). For subjective criteria, we use model-based grading. The result is a benchmark signal backed by inspectable artifacts: patches, logs, screenshots, and trajectories. We refresh the suite as VS Code and agent usage evolve, ranging from small sanity checks to harder, multi-step workflows that stress planning, context management, and tool choice. Together with public benchmarks, VSC-Bench gives us a more balanced signal: public evals tell us how a model compares to the field, while product-specific evals tell us whether it is ready for the experience developers expect inside VS Code. -## The Model Is the Engine. The Harness Is the Car. +## The model is the engine. The harness is the car. -We started with a question developers ask every few months: which model is best? The answer we keep arriving at is: it's not just the model. It's the context it sees, the tools it can reach, the loop that keeps it going, and the evaluation that makes sure it all works. That's the harness, and it's what we spend most of our engineering time on. +We started with a question developers ask every few months: which model is best? But for a coding agent, that question is a little like asking: which engine is best? The engine matters, but it's not enough on its own. It's the context the model sees, the tools it can reach, the loop that keeps it going, and the evaluation that makes sure it all works. That's the harness, and it's what we spend most of our engineering time on. As models gain new capabilities like longer context, better planning, and native tool use, the harness evolves to take advantage of them. And as developers push agent mode into new workflows, we feed what we learn back into the loop, the tools, and the evaluations. Every VS Code release ships harness improvements alongside model updates. diff --git a/blogs/2026/05/01/agent-loop.png b/blogs/2026/05/01/agent-loop.png new file mode 100644 index 0000000000..057b1df364 --- /dev/null +++ b/blogs/2026/05/01/agent-loop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2193a07996d35bb2ff0f6442e7c5a75c72cfd7226f2d7dbe442335647df8713 +size 571121 diff --git a/blogs/2026/05/01/agent_model_harness.png b/blogs/2026/05/01/agent_model_harness.png index 1e9a0be401..d941a30281 100644 --- a/blogs/2026/05/01/agent_model_harness.png +++ b/blogs/2026/05/01/agent_model_harness.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:60efa287b4aa9e669f4f997a6053a0973adf33bb603cf51ff8c60d3cc7239c01 -size 87681 +oid sha256:ed279723cca5f8ade9de0d538ed6f62c30fb8c3037e6d42d9d368adf53785bf3 +size 126439 diff --git a/blogs/2026/05/01/evaluations.png b/blogs/2026/05/01/evaluations.png index 6ed72a6ed7..2061dc6c28 100644 --- a/blogs/2026/05/01/evaluations.png +++ b/blogs/2026/05/01/evaluations.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06fa3d3de1800c1191e013041b7df77418f6e02555bf21aaa5b66f099892088f -size 192487 +oid sha256:d2c160ddbf6fc73757c601064cc4347245d709f94343fc9dde15a2e9b7a8401e +size 239620 diff --git a/blogs/2026/05/01/model_provider_loop.png b/blogs/2026/05/01/model_provider_loop.png index 5b94c17ab3..091c9087a9 100644 --- a/blogs/2026/05/01/model_provider_loop.png +++ b/blogs/2026/05/01/model_provider_loop.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d2c53ad860ebb4ee120e316991a143ffebe8ebaf8476b66fca9afb54779ac839 -size 345307 +oid sha256:7125a1a689a1f101ef121c3dd7a26f71a50d65cb3e14de154946c07961841c27 +size 372335 From d102bd0817f966b1c37566237f3b195e32cc4a79 Mon Sep 17 00:00:00 2001 From: Julia Kasper Date: Thu, 7 May 2026 18:02:07 -0700 Subject: [PATCH 4/4] Update blog images and copy --- .../01/agent-harnesses-github-copilot-vscode.md | 16 +++++----------- blogs/2026/05/01/agent.png | 3 +++ blogs/2026/05/01/agent_model_harness.png | 3 --- 3 files changed, 8 insertions(+), 14 deletions(-) create mode 100644 blogs/2026/05/01/agent.png delete mode 100644 blogs/2026/05/01/agent_model_harness.png diff --git a/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md b/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md index 2cb2f2db11..4b06522b0b 100644 --- a/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md +++ b/blogs/2026/05/01/agent-harnesses-github-copilot-vscode.md @@ -14,7 +14,7 @@ May 7, 2026 by [Julia Kasper](https://github.com/jukasper) With each new model release, the same conversation is reignited. Which model is the smartest? Which one is fastest? Which one should we use? Those are useful questions, but for a product like Visual Studio Code the model is only one part of the agentic coding experience. What developers actually interact with is the coding harness: the layer that assembles context, exposes tools, runs the agent loop, interprets tool calls, and turns a model's output into something useful inside the editor. In this post, we'll look at what that harness does, why it matters, and how we evaluate it as models and developer workflows evolve. -![Diagram showing that an agent is made up of a model plus a harness. The harness includes the agent loop, tools, context management, and system prompt.](agent_model_harness.png) +![Diagram showing that an agent is made up of a model plus a harness. The harness includes the agent loop, tools, context management, and system prompt.](agent.png) ## What is the coding harness? @@ -34,19 +34,13 @@ The logic that orchestrates these tasks, deciding when to continue or stop itera ## The agent loop -At its core, when you use an agent in VS Code, a tool-calling loop happens: a **"think → act → observe → think again" cycle**. On each iteration, the agent harness builds the prompt (system instructions + context + history + all tool results so far), sends it to the model, and checks the response. - -If the response includes tool calls, the harness executes those tools, captures their results, and loops back. If there are no tool calls, the loop can finish and the assistant’s text becomes the final response. +At its core, when you use an agent in VS Code, a tool-calling loop happens: a **"think → act → observe → think again"** cycle. On each iteration, the agent harness builds the prompt (system instructions + context + history + all tool results so far), sends it to the model, and checks the response. If the response includes tool calls, the harness executes those tools, captures their results, and loops back. If there are no tool calls, the loop can finish and the assistant’s text becomes the final response. ![Simplified diagram of the VS Code agent loop: the user sends a chat message, the tool-calling loop builds a prompt, sends it to the model, executes requested tools, records results, checks loop-control conditions, and either continues or finalizes the chat result.](agent-loop.png) -A **turn** is the user-visible chat exchange: you send one message, and the agent eventually produces a response. During that turn, the agent loop may perform many **rounds**. A round is one pass through the loop: build the prompt, call the model, receive text and/or tool calls, execute any tools, record the results, and decide whether to continue. The full execution of all those rounds is the loop’s **run**. - -A single user turn might trigger many rounds as the model searches files, reads code, edits files, runs tests, reads the output, and iterates on failures. - -The tool-calling loop is bounded by loop-control checks. We enforce a tool-call limit, checks for cancellation between rounds, and runs stop hooks. Stop hooks are extension points that can inspect the agent state and either allow it to finish or push it to keep working. +A **turn** is the user-visible chat exchange: you send one message, and the agent eventually produces a response. During that turn, the agent loop may perform many **rounds**. A round is one pass through the loop: build the prompt, call the model, receive text and/or tool calls, execute any tools, record the results, and decide whether to continue. The full execution of all those rounds is the loop’s **run**. A single user turn might trigger many rounds as the model searches files, reads code, edits files, runs tests, reads the output, and iterates on failures. -Within the loop, the prompt is rebuilt on every iteration. That means the model always sees the latest state of the workspace: if it edited a file three rounds ago, the current prompt reflects that edit. The harness also manages conversation summarization. When the accumulated history grows too large, it compresses earlier rounds into a summary so the model can keep working without hitting the context window ceiling. +The tool-calling loop is bounded by loop-control checks. We enforce a tool-call limit, check for cancellation between rounds, and run stop hooks. Stop hooks are extension points that can inspect the agent state and either allow it to finish or push it to keep working. Within the loop, the prompt is rebuilt on every iteration. That means the model always sees the latest state of the workspace: if it edited a file three rounds ago, the current prompt reflects that edit. The harness also manages conversation summarization. When the accumulated history grows too large, it compresses earlier rounds into a summary so the model can keep working without hitting the context window ceiling. ### Why do we need an agent loop? @@ -94,7 +88,7 @@ We still run these benchmarks. They are useful regression tests. But when we dec That's why we built VSC-Bench, our offline evaluation suite for VS Code agent behavior. VSC-Bench focuses on VS Code-specific developer tasks that public benchmarks do not cover well: custom agent modes, extension workflows, MCP and tool use, terminal and browser interaction, multi-turn conversations, and multi-language coding tasks across TypeScript, Python, C++, and others. -![Scatter chart comparing VSC-Bench model resolution rate against median total tokens, with each point representing a different model.](vscbench.png) +![Scatter chart comparing VSC-Bench model resolution rate against median total tokens, with each point representing a different model.](benchmark.png) For example, one task asks the agent to scaffold a new API endpoint, write a test, run it, and fix any failures. The assertions check that the route exists, the test passes, and that the agent used the terminal to verify its work rather than just writing code and stopping. diff --git a/blogs/2026/05/01/agent.png b/blogs/2026/05/01/agent.png new file mode 100644 index 0000000000..2f3b372c42 --- /dev/null +++ b/blogs/2026/05/01/agent.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5c6976d65d192b9d61d64eecad98ba3176797564b8760621b61e543e292cee3 +size 131436 diff --git a/blogs/2026/05/01/agent_model_harness.png b/blogs/2026/05/01/agent_model_harness.png deleted file mode 100644 index d941a30281..0000000000 --- a/blogs/2026/05/01/agent_model_harness.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ed279723cca5f8ade9de0d538ed6f62c30fb8c3037e6d42d9d368adf53785bf3 -size 126439