Agent Mode

This content was generated with the assistance of AI and should be verified against the official documentation of each tool and framework before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

This page targets VS Code’s current Copilot Chat (with its agent-harness picker and per-tool approval settings) and the Claude Code CLI’s agentic loop, both checked against VS Code’s agents documentation and Claude Code’s official docs as of 2026-09-28; both products change these screens and setting names often, so re-check the linked pages before relying on an exact label. The running example is the same DocsAssistant API Spring Boot + Python sample used throughout this sub-section, with its controller at src/main/java/com/example/docsassistant/DocsController.java and its tests under src/test/java/com/example/docsassistant/.

Copilot agent mode in VS Code

Selecting an agent

Copilot Chat runs a task through one of several agent harnesses — a harness is the runtime that manages the session’s tool calls, context and code changes. As of the date above, VS Code ships:

Harness What it runs

Local

Interactively, inside VS Code’s own extension host, using built-in and extension-contributed tools — the best fit for a quick interactive change with immediate feedback.

Copilot

Locally, powered by the Copilot SDK’s own Agent Host — the general-purpose default for everyday coding tasks, including background sessions.

Claude

Locally, using Anthropic’s Claude Agent SDK, exposing Claude Code’s own permission modes inside VS Code.

Codex

Locally, using OpenAI’s Codex harness, for interactive or background tasks.

Cloud

Remotely, against a GitHub repository, for a well-scoped task that can run unattended and come back as a pull request — covered in depth on Cloud & Background Agents.

A harness and an agent are picked from the same control at the bottom of the Chat view; which harnesses appear there depends on which agent-provider extensions are installed. See VS Code — Choose an agent harness.

Tools and terminal access

Whichever harness runs the session, it acts through tools — reading and searching files, editing them, running terminal commands, and calling anything an MCP server exposes. Which tools are available to a given request is configured from a tools picker in the chat input (Configure Tools, for the Local harness) or, persistently, from the Agent Customizations editor’s Tools tab (opened from the gear icon), where individual tools and whole tool sets can be turned on or off. A tool set groups related tools under one name so a prompt or a custom agent can pull them in together with #, for example #web for every web-related tool at once. See VS Code — Use tools with agents.

Terminal commands are a tool like any other, subject to the approvals below, but VS Code also runs the command detection described there against the shell’s own grammar (bash or PowerShell) to tell a read-only command from a risky one.

Approvals and auto-approve settings

By default, a terminal command or other tool call that is not auto-approved pauses and shows a confirmation with the tool’s name and its input, which you approve or reject before it runs. File edits inside the workspace work differently: the agent applies and saves them straight away, and you then Keep or Undo each change (in an Agent Host session, such as the Copilot harness, the edits have no pending review state at all). Only edits to sensitive files and to paths outside the workspace ask for approval before they are applied. Three settings loosen the per-tool confirmations, each with a real risk attached (see VS Code — Review code edits for the edit flow):

Setting What it does Risk of enabling it

chat.tools.terminal.autoApprove

Lists commands (by exact match, glob or a /regex/) that run without a prompt; VS Code’s own docs describe common read-only commands as auto-approved by default, with commands such as rm or del still requiring approval.

Command detection is best-effort: an obfuscated or chained command can evade the pattern and still run unattended.

chat.tools.edits.autoApprove

Lists file-path patterns whose edits apply without a confirmation; common system folders, dotfiles and files outside the workspace still require one by default.

A broad pattern can let an agent overwrite a file you did not mean to hand it, such as a CI config or a credentials file that happens to match the glob.

chat.tools.global.autoApprove

Auto-approves all tools in every workspace, removing the confirmation prompts entirely; the first time you enable it, VS Code shows a warning dialog asking you to confirm.

Nothing an agent does is confirmed any more — file edits, terminal commands and external tool calls all run unattended, in every workspace you open, including one whose contents you have not reviewed.

The same trade-off appears in the permissions picker in the chat input, which sets the level for the current session:

Level Behaviour and risk

Manual

The default: the tool, URL and terminal approval rules above apply, and anything they do not auto-approve asks for confirmation.

Assisted

A language model judges each tool call and auto-approves the ones it assesses as safe; the rest ask for confirmation. The model-based risk assessment can make mistakes, so it does not replace your own review.

Allow all

Runs every tool call without confirmation, including potentially destructive file edits, terminal commands and external tool calls.

Autopilot

Not a permission level but an agent mode, picked from the same chat input: it auto-approves every tool and keeps working, retrying on errors, until the agent decides the task is complete. It carries the same risk as Allow all, over a longer unattended run.

VS Code’s own documentation is explicit that terminal auto-approval "is a best-effort convenience, not a security boundary," and recommends running agent sessions in a sandbox or container for anything higher-risk than the DocsAssistant API sample. See VS Code — Manage approvals and permissions.

Claude Code’s equivalent loop

Claude Code runs the same three-phase loop —  gather context, take action, verify — introduced on Getting Started with Claude Code, and the active permission mode (default, acceptEdits, plan or auto, cycled with Shift+Tab) plays the same role as VS Code’s approval settings above: it decides which of the loop’s actions — file edits, and the filesystem or shell commands the CLI classifies as safe — run without asking first. There is no separate "agent mode" to turn on: every claude session is already running this loop, and the IDE and JetBrains integrations run the identical loop with the extension only changing where diffs are displayed. See Claude Code — Choose a permission mode.

How agents gather context

Before editing anything, both tools spend part of the loop gathering context on their own, mixing three kinds of action:

  • Search — a semantic or text search over the workspace to find the files relevant to the request, the way Copilot’s #codebase reference or Claude Code’s own search tool locate DocsController from a prompt that only names the endpoint.

  • Read — opening the files that search turned up (and, for Claude Code, any CLAUDE.md in their directory) to see the current code before proposing a change.

  • Run — executing a read-only command, such as running the existing test suite once to see which test fails, before writing any fix.

An explicit reference (#DocsController.java in Copilot Chat, @src/main/java/com/example/docsassistant/DocsController.java in Claude Code) skips the search step and points the agent straight at the right file, which is faster and less prone to picking the wrong candidate than leaving it to search alone. See VS Code — Add context to chat and Claude Code — Common workflows.

Approving tool calls

Reviewing a proposed change is the same idea in both tools, shown differently:

In GitHub Copilot (VS Code)
Copilot wants to run: mvn -q -Dtest=DocsControllerTest test
[ Continue ]  [ Skip ]
In Claude Code
Bash(mvn -q -Dtest=DocsControllerTest test)
Do you want to proceed?
1. Yes
2. Yes, and don't ask again for mvn commands in this project
3. No, tell Claude what to do differently

Approving once lets that single call through; the second option in each tool (an auto-approve rule, or Claude Code’s "don’t ask again") is what widens future approval, with the risks described above. See VS Code — Manage approvals and permissions and Claude Code — Choose a permission mode.

Stopping and steering mid-run

An agent that has gone down the wrong path does not need to be interrupted by closing the session. In VS Code, selecting Stop (or the equivalent Escape action) above the in-progress response stops the current tool call, and typing a correction in the chat box continues the same request instead of starting a new one. In Claude Code, pressing Esc stops the current tool call immediately, and typing a correction without pressing Esc first queues it — Claude reads the message as soon as the tool calls in flight finish, rather than mid-edit. Both are cheaper than letting a plausible-looking but wrong change keep compounding across several more turns. In Claude Code, pressing Esc twice (or running /rewind) also opens the rewind menu to restore an earlier conversation and code state. See Claude Code — Best practices: course-correct early and often and Claude Code — Interactive mode.

Tool sets and using existing MCP servers

An MCP (Model Context Protocol) server adds tools an agent did not ship with — for example, one that queries DocsAssistant API’s own Postgres database directly instead of the agent guessing at the schema from source. Building a server is out of scope here and is the subject of the Model Context Protocol (MCP) sub-section; this page covers only pointing an existing server at each tool.

In VS Code
// .vscode/mcp.json
{
  "inputs": [
    {
      "type": "promptString",
      "id": "docsassistant-dsn",
      "description": "DocsAssistant read-only Postgres DSN",
      "password": true
    }
  ],
  "servers": {
    "docsassistant-db": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@bytebase/dbhub", "--dsn", "${input:docsassistant-dsn}"]
    }
  }
}

The file is meant to be committed, so it holds no credentials: the inputs entry makes VS Code prompt for the connection string (masked, because of password: true) the first time the server starts, and substitutes it wherever ${input:docsassistant-dsn} appears. VS Code’s MCP docs advise against hardcoding secrets such as a database password; an envFile field that loads variables from an uncommitted file is the other option. See VS Code — MCP configuration reference: input variables for sensitive data.

VS Code also discovers project-portable .mcp.json files (top-level mcpServers key) and a user-level configuration opened with the MCP: Open User Configuration command; running MCP: Add Server from the Command Palette writes to whichever of these you target. Once added, a server’s tools appear in the same tools picker described above, grouped under its name. See VS Code — Use MCP servers in VS Code.

In Claude Code
$ export DOCSASSISTANT_DB_DSN="postgresql://readonly:<password>@localhost:5432/docsassistant"
$ claude mcp add --transport stdio docsassistant-db -- npx -y @bytebase/dbhub \
    --dsn "$DOCSASSISTANT_DB_DSN"
$ claude mcp list
$ claude
> /mcp

claude mcp add takes a --scope of local (the current project only), project (written to a shared .mcp.json checked into the repository) or user (every project); /mcp inside a running session shows connected servers and their status. The shell expands $DOCSASSISTANT_DB_DSN when the server is added, and the default local scope stores the result in ~/.claude.json, outside the repository; for a checked-in project-scope .mcp.json, write ${DOCSASSISTANT_DB_DSN} in the file instead, which Claude Code expands from each developer’s own environment when it loads the server. See Claude Code — Connect to MCP servers.

Example: fixing a failing test in agent mode

Suppose DocsControllerTest#getPage_returns404WhenMissing fails after a refactor. The task, and the approvals it triggers, look like this in each tool.

In GitHub Copilot (VS Code)
#DocsControllerTest.java This test is failing. Run it, find out why, and fix DocsController.java
so it passes again.
Copilot wants to run: mvn -q -Dtest=DocsControllerTest test
[ Continue ]  [ Skip ]

Copilot edited DocsController.java (applied; review the diff)
[ Keep ]  [ Undo ]

Copilot wants to run: mvn -q -Dtest=DocsControllerTest test
[ Continue ]  [ Skip ]
In Claude Code
$ claude "DocsControllerTest#getPage_returns404WhenMissing is failing. Run it, find out why,
and fix @src/main/java/com/example/docsassistant/DocsController.java so it passes again."

Bash(mvn -q -Dtest=DocsControllerTest test)
Do you want to proceed?  1. Yes  2. Yes, and don't ask again  3. No

Edit(src/main/java/com/example/docsassistant/DocsController.java)
Do you want to make this edit?  1. Yes  2. Yes, and don't ask again  3. No

Bash(mvn -q -Dtest=DocsControllerTest test)
Do you want to proceed?  1. Yes  2. Yes, and don't ask again  3. No

Both runs follow the same loop — gather (open the failing test and the controller), plan (decide the fix), edit, run (the test again) and verify (read its output) — repeating the run/verify pair until the test passes or you stop it:

flowchart LR Gather["Gather context\n(search, read, run)"] --> Plan["Plan the fix"] Plan --> Edit["Edit files"] Edit --> Run["Run tests / commands"] Run --> Verify["Verify output"] Verify -->|test still fails| Gather Verify -->|test passes| Done["Done / waiting for you"]