Tool sets in VS Code: Stop agent hallucinations

Blog 14 min read

Visual Studio Code agents operate on a strict triad: built-in tools, Model Context Protocol (MCP) integrations, and extension utilities. The difference between a hallucinating bot and a productive engineer often comes down to how you curate this list. Agents do not guess; they select from what you enable. If you leave the floodgates open, the model will dredge up irrelevant capabilities or, worse, attempt dangerous operations on sensitive endpoints.

Security and accuracy start before the first token is generated. You must explicitly enable functions within the Chat view, filtering availability via the search box or by installing specific MCP servers. This isn't just housekeeping; it's a hard boundary against capability hallucination.

Beyond simple on/off switches, the real power lies in tool sets. These allow you to group utilities into single, referenceable entities, letting you override input parameters via the confirmation dialog before a single command hits the shell. This control layer ensures that while the agent handles the heavy lifting of searching code or fetching web content, you retain final authority. Modern development demands this balance: automation without oversight is just a faster way to break production.

The Role of Tool Sets in Agent Autonomy

Defining Tool Sets, Built-in Tools, and MCP Tools

Stop enumerating individual functions. A tool set groups multiple utilities into a single referenceable entity, simplifying prompt execution across chat prompts, prompt files, and custom chat agents. Instead of listing ten separate commands, you invoke a set like or . This abstraction cuts token overhead and standardizes agent behavior, ensuring your custom chat agents act consistently every time.

Availability hinges on source distinctions. Built-in tools like `read`, `write`, and `bash` come pre-enabled, handling basic filesystem or shell operations without external dependencies. MCP tools extend this baseline by connecting to installed Model Context Protocol servers, bridging the gap to external data sources or specialized APIs. While built-ins handle local code manipulation immediately, MCP tools expand the agent's reach to external systems through installed servers.

Automatic tool selection is a gamble when precision matters. Relying on it risks bloating your context window with irrelevant options. Explicitly referencing a tool set in a prompt forces the agent to prioritize specific capabilities, mitigating the risk of the model selecting a suboptimal tool from the global pool. Precision requires upfront investment: define these sets via `.jsonc` configuration files. Selecting only the tools necessary for a prompt improves results, balancing the flexibility of a large repertoire against the predictability of curated sets.

Using # References and Configuring Tool Sets

Typing # followed by a specific name in the chat input triggers explicit tool invocation. This syntax bypasses the agent's autonomous selection logic, forcing the application of an assigned capability. A dropdown list appears containing built-in utilities, MCP tools from external servers, and defined tool sets. Direct references eliminate ambiguity when multiple tools share similar functional descriptions or when precise execution order matters.

To create custom collections, run the Chat: Configure Tool Sets command within the Command Palette. Selecting Create new tool sets file generates a .jsonc configuration where you map logical names to arrays of underlying functions. Grouped entities simplify prompt engineering by allowing a single token, such as , to enable complex context-gathering workflows instantly. This abstraction reduces the cognitive load required to manage large inventories of available actions during extended sessions.

Control doesn't end at invocation. Expanding details via the chevron icon lets operators inspect and modify input parameters when a tool triggers a confirmation dialog. Selecting Allow finalizes the transaction with the updated arguments, ensuring no unintended code runs without oversight. Granular control over these permissions is necessary for managing how the agent requests approval and operates with autonomy. Autonomous loops risk executing destructive filesystem changes or exposing environment variables without strict confirmation policies. Increased interaction frequency is the cost of this safety layer, requiring builders to balance autonomy levels against operational risk tolerance carefully.

Managing Tool Availability and Shell Integration

The tools picker in the Chat view enables users to enable or disable tools on a per-request basis. A chat request can have a maximum of 128 tools enabled at a time. If you hit the "Cannot have more than 128 tools per request" error, open the tools picker in the Chat view and deselect some tools or entire MCP servers. This forces a strategic choice between broad capability coverage and deep, specialized function access within a single session. Curating tool sets to group related functions allows bulk enabling without exceeding practical limits.

Shell execution is a frequent requirement, used by agents to install dependencies or run builds. Specific shell compatibility details vary by environment, yet the agent uses the terminal to execute commands autonomously based on the prompt. Understanding the active terminal context is necessary for troubleshooting agent behavior when teams manage diverse developer environments.

Inside the Agent Tool Selection and Execution Loop

Autonomous Tool Selection and Explicit # Referencing

Agents pull from the enabled tools set, picking utilities that match the prompt context and request scope. This autonomous selection weighs built-in tools, MCP integrations, and extension tools to handle jobs like running terminal commands or searching codebases. Typing # in the chat input reveals the full inventory of accessible utilities, allowing precise control over the execution loop. Users can override automatic choices by explicitly referencing a tool with the # symbol followed by the name, forcing the agent to apply specific functionality such as for external queries or for internal analysis. Explicit referencing narrows the search space so the agent focuses computational resources on the intended operation rather than guessing from the full tool set.

Executing Terminal Commands and Configuring Output Location

The terminal tool is one of the most frequently used built-in tools, utilized by the agent to run commands like installing dependencies, running builds, or executing scripts. This mechanism delegates command strings directly to the host shell, allowing the agent to modify the environment or compile assets as part of a workflow. Unlike IDE-bound tools that often restrict shell access, terminal-based alternatives provide direct `bash` tool integration for unrestricted command execution. By default, tool call details are collapsed in the chat conversation. Users can uncollapse them by selecting the tool summary line in chat, or change the default behavior with the `chat.agent.thinking.collapsedTools` setting (experimental).

Managing Long-Running Tasks with Background Execution and Timeouts

When the agent initiates a blocking command, users can review and edit input parameters before the tool runs. When the tool confirmation dialog appears, select the chevron next to the tool name to expand its details, edit any tool input parameters as needed, and select Allow to run the tool with modified parameters. This step ensures the agent operates with the correct configuration before proceeding. A Continue in Background button appears next to the terminal command in the chat conversation while a command is running. Selecting this button moves the command to the background, where it continues running, allowing the agent to check output later or use the terminal for other tasks. The system allows users to control how the agent requests approval for tool calls and how much autonomy it has. Some extensions allow configuration of the shell used by the bash tool, yet users should verify that the integrated terminal profile matches their local development constraints before delegating build tasks.

  1. Inspect the tool confirmation dialog for parameter accuracy.
  2. Expand the tool details using the chevron icon.
  3. Modify input values to suit the current workflow needs.
  4. Validate the active shell profile matches the project's runtime requirements.

Configuring and Executing Tools for Development Workflows

Defining Tool Set Structure in JSONC Configuration Files

Map specific built-in tools, MCP utilities, and extension capabilities into named groups by constructing a `.jsonc` file. Generate the initial file structure by executing the Chat: Configure Tool Sets command or accessing the ellipsis menu in the Chat view. The resulting configuration object requires a `tools` array listing exact identifiers, a `description` string for the picker interface, and an `icon` reference from the Product Icon library. This schema enables the tool set to function as a single selectable entity when prefixed with `#` in prompts. Organizing utilities this way reduces prompt token consumption by avoiding repetitive tool enumeration during complex queries. Grouping too many heavy utilities into one set can obscure individual tool failures during debugging sessions. Developers must balance granular control against the convenience of bulk enabling related functions. The structure supports custom tool creation via helper functions, extending beyond standard built-in tools like `grep` or `bash`. Precise naming in the tools array is mandatory; a single typo prevents the agent from locating the underlying executable. AI Agents News recommends validating syntax before relying on these sets for autonomous workflows.

Executing Terminal Commands via Integrated VS Code Terminals

Invoke the terminal tool to execute dependency installs and build scripts within the integrated shell environment. Developers initiate this workflow by enabling specific utilities in the tools picker before submitting a request to the chat interface. When the model determines a command is necessary, it renders the proposed script directly in the conversation thread for review. Users inspect output inline by selecting Show Output or switch to the full integrated terminal view via the Show Terminal action. This dual-view architecture supports both quick verification and deep debugging without leaving the editor context.

  1. Select the Configure Tools button in the chat input field.
  2. Toggle the terminal switch to enable command execution capabilities.
  3. Submit a prompt requiring environment changes, such as installing packages.
  4. Review the generated command and select Allow to proceed.
  5. Click Continue in Background if the process requires extended runtime.

Run long-running processes like development servers asynchronously, freeing the agent to perform other diagnostic tasks while monitoring status. Background execution prevents blocking the conversational loop during watch-mode builds. Pushing commands to the background introduces state management complexity, as the agent must later retrieve output from a detached session context. OpenCode provides a terminal-first alternative with built-in bash capabilities, yet the VS Code approach tightly couples execution visibility with chat history. The constraint favors immediate context retention over the raw process isolation found in standalone terminal-based ai tools. AI Agents News recommends configuring output locations via experimental settings to balance token usage against operational visibility.

Validating Background Execution Times and Output Locations

Stop waiting for terminal output once a specified timeout expires, returning only the data collected until that interruption. Operators must explicitly configure this limit within the tool parameters to prevent indefinite hangs during long-running builds or server startups.

  1. Open the tool confirmation dialog and expand the input details using the chevron control.
  2. Modify the timeout value to match the expected duration of the background task.
  3. Verify the `chat.tools.terminal.outputLocation` setting directs logs to the integrated terminal for continuous monitoring.
Configuration Behavior Risk
Inline Output Truncates after timeout Lost context
Integrated Terminal Retains full stream High memory use

Edit these parameters before execution to ensure the permission every step of the way philosophy remains intact while accommodating asynchronous workflows. A common failure mode involves agents attempting to read partial files before the background process flushes buffers. Aggressive timeouts produce incomplete build artifacts that force manual re-execution. Proper validation requires testing against actual compilation durations rather than estimated values. AI Agents News recommends aligning timeout thresholds with the slowest expected CI job in the repository.

Optimizing Tool Usage and Resolving Common Configuration Errors

Defining the 128-Tool Limit and Virtual Tool Thresholds

A single chat request supports a maximum of 128 enabled tools before the system rejects the configuration. When an agent exceeds this count, users must manually deselect specific MCP servers or individual utilities via the tools picker to restore functionality. This hard constraint prevents context window overflow but creates friction for developers relying on extensive plugin ecosystems. To address this scaling issue, the `github.copilot.chat.virtualTools.threshold` setting allows automatic management of large tool sets without manual intervention. Enabling every available utility is rarely optimal because excessive tool definitions degrade agent reasoning speed and increase token consumption. OpenCode includes a set of built-in tools by default, yet even thorough suites require selective activation for peak performance. Automatic thresholding may hide specialized tools the agent needs for niche tasks, requiring occasional manual verification. Operators should group related functions into logical sets rather than enabling all extensions globally. This approach balances the breadth of available actions with the strict input limits of the underlying model.

Resolving 'Cannot Have More Than 128 Tools' Errors via Tools Picker

The system rejects any chat request exceeding 128 enabled tools, requiring immediate reduction via the tools picker. This hard limit prevents context overflow but forces explicit selection when integrating multiple MCP servers or extension tools. Operators encountering this error must open the Chat view, select the Configure Tools button, and deselect non-necessary utilities or entire server groups. Typing `#` in the input field reveals the full inventory, allowing precise identification of active components before removal. Alternatively, enabling the `github.copilot.chat.virtualTools.threshold` setting automates this management by dynamically loading tools only when needed. Automating tool selection reduces manual configuration overhead but introduces latency during initial tool invocation. Virtual thresholds solve the count error, yet they shift the bottleneck from memory limits to runtime resolution speed. Developers extending functionality through custom tool creation must account for this ceiling during architecture planning. Failing to prune the active set degrades agent reasoning cycles as the model parses irrelevant schema definitions. AI Agents News recommends auditing tool sets quarterly to align active definitions with current workflow requirements rather than retaining legacy integrations.

Shell Integration Failures with Default cmd and sh Configurations

Shell integration fails when agents default to cmd on Windows or sh on macOS, severing the feedback loop required for reliable automation. Because these legacy shells lack modern escape sequence support, the agent cannot distinguish command output from the prompt, forcing reliance on idle timeouts rather than explicit completion signals. This architectural gap creates a "slow and flaky experience" where execution timing becomes unpredictable. Operators configuring profiles via `chat.tools.terminal.terminalProfile.windows` or equivalent Linux settings must recognize that overriding defaults to use PowerShell or zsh is mandatory for stable workflows. Some terminal-first environments like OpenCode allow explicit shell configuration to bypass host constraints, but the native VS Code agent remains bound by the host terminal's capabilities. The cost of retaining sh is measurable: agents miss error codes hidden in unstructured text streams, leading to cascading logic failures in multi-step tasks. Unlike Cline, which enforces guarded workflows with explicit permissions for every file change, the standard agent assumes environmental stability that cmd cannot provide. Builders must treat shell selection as a hard dependency, not a preference, to prevent silent execution drift. AI Agents News recommends validating terminal profiles before deploying complex tool sets.

About

Diego Alvarez, Developer Advocate at AI Agents News, brings hands-on expertise to this guide on using tools within Visual Studio Code. His daily work involves building and benchmarking autonomous agents using frameworks like CrewAI and LangGraph, where effective tool use and function calling are critical for moving beyond simple chat to actual task execution. This practical experience directly informs the article's focus on managing built-in tools, Model Context Protocol (MCP) integrations, and extension tools. At AI Agents News, Diego prioritizes honest, technical education for engineers, ensuring readers understand not just how to enable these capabilities, but also their reliability and failure modes. By connecting his routine agent development workflows to VS Code's evolving feature set, he provides the precise, actionable guidance developers need to implement reliable agentic systems without the hype.

Conclusion

Scaling autonomous coding agents reveals that environmental fragility outweighs model intelligence when legacy shells like cmd or sh obscure execution signals. The operational cost here is not merely latency but silent logic drift, where unstructured text streams cause agents to miss critical error codes, leading to cascading failures in multi-step tasks. While the industry pivots toward agents capable of full task execution, relying on default host configurations creates a ceiling that pruning tool definitions alone cannot fix. You must treat shell selection as a hard dependency rather than a cosmetic preference to ensure reliable automation.

Start by auditing your terminal profiles this week to explicitly enforce PowerShell or zsh across all development environments, overriding any system defaults that rely on legacy interpreters. This configuration change is mandatory before expanding your agent's permissions or integrating complex custom tools, as stable feedback loops are prerequisites for advanced autonomy. Do not assume environmental stability; instead, validate that your host terminal can distinguish command output from prompts without relying on unpredictable idle timeouts. Only by securing this fundamental layer can you prevent the degradation of agent reasoning cycles caused by parsing irrelevant schema definitions or unstructured error streams.

Frequently Asked Questions

Unrestricted access causes the agent to select suboptimal utilities from the global pool. Limiting availability improves output quality by a portion through focused context usage.

Type a hash symbol followed by the tool name to trigger explicit invocation. This direct reference prevents ambiguity and ensures the correct function runs a portion faster.

Expand the chevron in the confirmation dialog to edit input parameters manually. This safety layer prevents unintended code execution while maintaining a portion operational control.

Grouping multiple utilities into a single referenceable entity cuts token overhead significantly. This abstraction standardizes behavior and improves prompt efficiency by a portion across sessions.

You must create a .jsonc file to map logical names to arrays of functions.

References