How to leverage tools in prompt orchestrations

Master the two-level tool architecture: YAML capability declarations and runtime tool calls. Complete catalog of built-in, MCP, and extension tools with selection strategies, token costs, and practical patterns.
Author

Dario Airoldi

Published

February 22, 2026

How to leverage tools in prompt orchestrations

Tools are the hands and eyes of your AI agents. Without them, an agent can only think—with them, it can search code, edit files, run commands, ask you questions, and delegate to other agents. This article is the definitive reference for understanding, selecting, and using tools effectively.

Up to this point in the series, you’ve learned how to create the building blocks of GitHub Copilot customization: prompt files, agent files, instruction files, skills, MCP servers, and hooks. Each of those articles mentioned tools—restricting them in agent YAML, referencing them in prompts, building them as MCP servers. But none explained what tools actually are at runtime, how they work under the hood, or how to choose the right tool for each situation.

This article fills that gap. It covers the complete tool architecture—from the YAML declarations you write to the runtime function calls the model makes—and gives you the knowledge to select, combine, and optimize tools for any prompt orchestration.

Table of contents


🎯 The two-level tool architecture

GitHub Copilot’s tool system operates at two distinct levels. Understanding this separation is essential for effective prompt engineering—confusing Level 1 and Level 2 is the most common source of tool-related mistakes.

Two names, two layers

Level What you write What runs Example
Level 1 — YAML declarations tools: ['codebase', 'editor'] in frontmatter Nothing directly—these are permissions codebase, editor, filesystem, fetch
Level 2 — Runtime tool calls The model invokes functions during execution Actual operations on your workspace read_file, grep_search, create_file, run_in_terminal

The relationship is hierarchical: Level 1 declarations enable groups of Level 2 runtime tools. When you write tools: ['editor'] in YAML, you’re granting the agent permission to use runtime tools like create_file, replace_string_in_file, and multi_replace_string_in_file. When you write tools: ['codebase'], you’re enabling semantic_search, grep_search, file_search, and read_file.

YAML Declaration (Level 1)         Runtime Tools Enabled (Level 2)
─────────────────────────────────────────────────────────────────
tools: ['codebase']          ───►  semantic_search, grep_search,
                                   file_search, read_file

tools: ['editor']            ───►  create_file, replace_string_in_file,
                                   multi_replace_string_in_file, read_file

tools: ['filesystem']        ───►  list_dir, file_search, read_file

tools: ['fetch']             ───►  fetch_webpage

tools: ['web_search']        ───►  (web search integration)

tools: ['search']            ───►  grep_search, file_search

tools: ['usages']            ───►  list_code_usages

tools: ['problems']          ───►  get_errors

tools: ['changes']           ───►  get_changed_files

What “always available” means

Some runtime tools are always available regardless of your YAML tools field. These can’t be restricted:

Always-Available Tool Purpose
manage_todo_list Track task progress in structured todo list
ask_questions Present structured questions to the user
runSubagent Delegate work to subagents
tool_search_tool_regex Discover deferred tools from MCP/extensions

This means even an agent with tools: ['codebase'] (read-only) can still track progress, ask the user for clarification, delegate to subagents, and discover MCP tools. You can’t create a truly “passive” agent—every agent has at least these four capabilities.


📋 Level 1: YAML capability declarations

Level 1 tools are what you write in the tools field of prompt and agent YAML frontmatter. They control what categories of operations an agent can perform.

Core built-in capabilities

Capability Description Read-Only Network Access
codebase Semantic search across workspace for code patterns, symbols, implementations Yes No
editor File read/write operations—create, modify, delete files No No
filesystem Directory navigation, file queries, metadata access Yes No
fetch Retrieve content from web URLs and REST APIs Yes Yes
web_search Search the internet for current information Yes Yes
search Workspace text search (exact string and regex) Yes No
usages Find code usages, references, and call hierarchies Yes No
problems Get compile errors, lint warnings from VS Code Yes No
changes View git changes and diffs Yes No

Tool sets (predefined groups)

VS Code provides predefined groups of related capabilities for convenience:

Tool Set Included Capabilities Use Case
#edit editor, filesystem Code modification workflows
#search codebase, search, usages Code discovery and analysis
#reader codebase, problems, changes, usages Context gathering without modification
# These are equivalent:
tools: ['codebase', 'search', 'usages']
tools: ['#search']

MCP server tools

Tools from Model Context Protocol servers use the @server-name prefix:

tools: ['codebase', '@github/*']      # All tools from GitHub MCP server
tools: ['editor', '@azure/deploy']     # Specific Azure tool only
tools: ['#search', '@company-wiki/*']  # Search + custom MCP

Built-in MCP servers:

Server Purpose Enable Setting
@github GitHub API—issues, PRs, repos, commits github.copilot.chat.githubMcpServer.enabled
@azure Azure resources, queries, documentation Azure extension required

For building your own MCP servers, see How to Create MCP Servers for Copilot.

Tool priority order

When multiple sources define tools, this priority order applies:

  1. Prompt file tools field (highest priority)
  2. Referenced agent’s tools field
  3. Default tools for current agent mode
# agent defines default tools
# security-reviewer.agent.md
---
tools: ['codebase', 'search', 'fetch']
---

# prompt overrides/extends them
# api-security-audit.prompt.md
---
agent: security-reviewer
tools: ['codebase', 'search', 'fetch', '@github/*']  # adds GitHub MCP
---

Common capability combinations

Profile Capabilities Use Case
Read-only ['codebase', 'filesystem', 'search'] Planning, research, review
Local edit ['codebase', 'editor', 'filesystem'] Refactoring, code generation
Research ['codebase', 'fetch', 'web_search'] Documentation, best practices lookup
Full local ['codebase', 'editor', 'filesystem', 'search', 'usages', 'problems'] Implementation agents
Unrestricted [] or omit field All available capabilities enabled

⚙️ Level 2: Runtime tool calls

Level 2 is where tools actually do things. When an agent runs, the model decides which runtime tools to call based on the task, context, and available capabilities. Each tool is a JSON-schema function with specific parameters, behaviors, and token costs.

Here’s the complete catalog of runtime tools, organized by function.


🔍 Search tools: finding the right information

Search is the most common tool category in prompt orchestrations. Choosing the right search tool is critical—using read_file on a 500-line file when grep_search would find the relevant line wastes thousands of tokens.

read_file

Purpose: Read the contents of a specific file, with line range control.

When to use:

  • You need to read specific lines from a known file
  • You’ve found a file via file_search or grep_search and need its content
  • You need to understand code before editing it

Key parameters:

  • filePath (required): Absolute path to the file
  • startLine (required): 1-based start line
  • endLine (required): 1-based end line (inclusive)

Token cost: ~10 tokens per line read. A 50-line read costs ~500 tokens; a 500-line read costs ~5,000 tokens.

Best practices:

  • Always specify line ranges—don’t read entire large files
  • Read larger ranges in fewer calls rather than many small reads
  • Use grep_search or file_search first to identify what to read

list_dir

Purpose: List the contents of a directory. Returns names of files and subdirectories.

When to use:

  • You need to understand project structure
  • You’re looking for files in a specific directory
  • You want to discover what’s available before searching

Key parameters:

  • path (required): Absolute path to the directory

Token cost: ~100-300 tokens (directory listings are compact)

Search tool decision tree

What are you looking for?
│
├── A concept, pattern, or idea ──────────► semantic_search
│
├── An exact string or regex ─────────────► grep_search
│   └── Within a specific file? ──────────► grep_search + includePattern
│
├── A file by name/pattern ───────────────► file_search
│
├── Content of a known file ──────────────► read_file (specify line range!)
│
└── Directory structure ──────────────────► list_dir

✏️ Edit tools: modifying the workspace

Edit tools change files on disk. They require the editor capability in YAML.

create_file

Purpose: Create a new file with specified content. Creates parent directories if they don’t exist.

When to use:

  • Creating new files (code, documentation, config)
  • Scaffolding project structures
  • Generating output artifacts

When NOT to use:

  • Editing an existing file (use replace_string_in_file)
  • Renaming or moving files (use run_in_terminal with mv)

Key parameters:

  • filePath (required): Absolute path for the new file
  • content (required): Complete file contents

Token cost: Primarily output tokens for the content generated. A 100-line file costs ~1,000 output tokens.

replace_string_in_file

Purpose: Replace exactly one occurrence of a literal string in an existing file. The key constraint: your oldString must match exactly one location in the file.

When to use:

  • Modifying existing code or content
  • Targeted edits where you know the exact context
  • Any edit where you need to preserve surrounding code

Key parameters:

  • filePath (required): Absolute path to the file
  • oldString (required): The exact literal text to replace (include 3+ lines of context before and after)
  • newString (required): The replacement text

Token cost: ~200-500 tokens per operation (context lines + replacement)

Best practices:

  • Include at least three lines of unchanged context before and after the target text
  • If the same string appears multiple times, add more context lines to disambiguate
  • For multiple edits to the same file, try multi_replace_string_in_file instead

multi_replace_string_in_file

Purpose: Apply multiple replacements in a single call—across the same file or different files. More efficient than sequential replace_string_in_file calls.

When to use:

  • Making several related edits across files
  • Batch-editing a single file with multiple changes
  • Refactoring operations that touch multiple locations

Key parameters:

  • explanation (required): Description of the batch operation
  • replacements (required): Array of {filePath, oldString, newString} objects

Token cost: Similar per-replacement cost as replace_string_in_file, but avoids the overhead of multiple tool round-trips.

Edit tool decision tree

What do you need to do?
│
├── Create a new file ────────────────────► create_file
│
├── Edit one location in a file ──────────► replace_string_in_file
│
├── Edit multiple locations ──────────────► multi_replace_string_in_file
│   (same file or different files)
│
└── Rename or move a file ───────────────► run_in_terminal (mv command)

🖥️ Execution tools: running commands

Execution tools run shell commands and inspect build/lint results.

run_in_terminal

Purpose: Execute PowerShell/shell commands in a persistent terminal session. The terminal preserves environment variables, working directory, and context between calls.

When to use:

  • Running build commands (dotnet build, npm install)
  • Running tests (pytest, npm test)
  • Git operations (git status, git diff)
  • Any operation that requires shell access

Key parameters:

  • command (required): The command to execute
  • explanation (required): One-sentence description shown to the user
  • goal (required): Short description of purpose
  • isBackground (required): true for long-running processes (servers), false for blocking
  • timeout (optional): Milliseconds before stopping output tracking

Token cost: Variable—depends on command output. Build outputs can be 2,000-10,000+ tokens. Use filtering (e.g., Select-Object -Last 20) to limit output.

Best practices:

  • Never run multiple run_in_terminal calls in parallel—they share a session
  • For long-running processes (servers, watch mode), use isBackground: true
  • Filter verbose output to reduce token consumption
  • Define explicit command boundaries in agent instructions (what’s ALLOWED vs. NEVER)

get_terminal_output

Purpose: Check the output of a previously started background terminal command.

When to use:

  • Checking on a background server you started
  • Getting build results from a background process

Key parameters:

  • id (required): Terminal ID returned by run_in_terminal

Token cost: Depends on accumulated output.

get_errors

Purpose: Get compile errors, lint warnings, and diagnostics from VS Code’s problems panel.

When to use:

  • After editing code to verify changes don’t introduce errors
  • Checking overall project health
  • Finding type errors, lint violations, import issues

Key parameters:

  • filePaths (optional): Specific files/folders to check. Omit for all errors.

Token cost: ~50-200 tokens per error. A clean project returns minimal tokens.


💬 Interaction tools: communicating with users

These tools let the agent interact with the user during execution. They’re always available—you can’t restrict them.

ask_questions

Purpose: Present structured questions to the user with predefined options. The only way to get explicit user input during prompt execution without interrupting the flow.

When to use:

  • Clarifying ambiguous requirements before proceeding
  • Getting user preferences on implementation choices
  • Confirming decisions that meaningfully affect the outcome

When NOT to use:

  • The answer is determinable from code or context
  • Asking permission to continue or abort (just proceed)
  • Reporting a problem (attempt to resolve it instead)
  • Quizzes or polls (recommended options are pre-selected and visible—they’d reveal answers)

Key parameters:

  • questions (required): Array of 1-4 questions, each with:
    • header (required): Short label (max 12 chars)
    • question (required): Full question text
    • options (optional): 0-6 options with label, description, recommended
    • multiSelect (optional): Allow multiple selections
    • allowFreeformInput (optional): Allow custom text alongside options

Token cost: ~300-500 tokens per question set (the question definition + user response).

Example prompt guidance:

If the user's intent is ambiguous, use ask_questions to clarify.
Batch related questions into a single call (max 4 questions).
Provide a sensible default as the recommended option so users can confirm quickly.

manage_todo_list

Purpose: Maintain a structured todo list visible in the chat UI. Tracks task progress with explicit state transitions.

When to use:

  • Complex multi-step work requiring planning and tracking
  • When the user provides multiple tasks or requests
  • Before starting work on any major step (mark as in-progress)
  • Immediately after completing each step (mark as completed)

When NOT to use:

  • Single, trivial tasks completable in one step
  • Purely conversational or informational requests
  • Simple file reads or searches

Key parameters:

  • todoList (required): Complete array of all todo items, each with:
    • id (required): Sequential number starting from 1
    • title (required): Concise 3-7 word action label
    • status (required): not-started, in-progress, or completed

Token cost: ~500 tokens overhead for a 5-step workflow (the full list is sent with every update).

How it works:

manage_todo_list serves two purposes:

  1. User visibility: Shows a live progress tracker in the chat UI, so the user can see what the agent is doing, what’s next, and what’s done
  2. Agent reliability: Acts as explicit state checkpointing—the agent commits to a task before starting it and records completion, reducing the chance of skipped steps or going in circles

The tradeoff is token cost vs. reliability. For a five-step workflow, the overhead is ~500 tokens across all updates. That’s negligible compared to the 50,000+ tokens a five-step orchestration typically consumes.

Best practices:

## Task Management

- Create a todo list at the start of multi-step work
- Mark ONE todo as in-progress at a time
- Mark each todo completed IMMEDIATELY after finishing it
- Don't batch completions—update status individually

When to use - [ ] checkboxes instead: Markdown checkboxes (- [ ] Step 1, - [x] Step 2) are a lighter-weight alternative that some models recognize as task tracking signals. They don’t render in the UI or provide the same reliability guarantees as manage_todo_list, but they cost zero additional tokens since they’re just part of the prompt content.


🤝 Delegation tools: orchestrating agents

Delegation tools let agents spawn other agents to handle subtasks. They’re always available.

runSubagent

Purpose: Launch a new agent to handle a complex, multi-step task autonomously. The subagent gets its own clean context window and returns a single summary.

When to use:

  • Complex tasks that benefit from isolated, focused context
  • Research or analysis that would bloat the main agent’s context
  • Tasks requiring different tools or model than the main agent

When NOT to use:

  • Simple tasks completable in one or two tool calls
  • Tasks that need the main conversation’s full context

Key parameters:

  • prompt (required): Detailed task description for the subagent
  • description (required): Short 3-5 word summary
  • agentName (optional): Name of a specific custom agent to invoke

Token cost: The subagent consumes its own token budget. Only the final summary (typically 500-2,000 tokens) returns to the main context.

For complete subagent orchestration patterns, see How to Design Subagent Orchestrations.

tool_search_tool_regex

Purpose: Discover and load deferred tools from MCP servers and VS Code extensions. This is the meta-tool—it makes other tools available.

When to use:

  • Before calling any MCP tool (e.g., mcp_github_*, mcp_azure_*)
  • Before calling any deferred extension tool
  • When you need to discover what tools are available from a specific server

When NOT to use:

  • For tools already loaded by a previous search
  • For built-in tools (they’re always available)

Key parameters:

  • pattern (required): Python regex pattern matched case-insensitively against tool names, descriptions, and parameters

Token cost: ~200-500 tokens per search (returns matching tool schemas).

How deferred loading works:

Not all tools are loaded at startup. MCP server tools and VS Code extension tools are deferred—they don’t exist until you search for them. The workflow:

1. Agent needs to call mcp_github_create_issue
2. Agent first calls: tool_search_tool_regex("mcp_github_create")
3. Tool schema is returned and loaded into the session
4. Now agent can call mcp_github_create_issue normally

This lazy-loading mechanism keeps startup fast and avoids overwhelming the context with hundreds of tool schemas. But it means you must search before you call—calling a deferred tool directly will fail silently.


🔌 Tool sources: built-in vs. MCP vs. extensions

Tools come from three distinct sources, each with different loading mechanisms, availability, and characteristics.

Architecture overview

┌─────────────────────────────────────────────────────────────┐
│  VS CODE (Host)                                              │
│                                                              │
│  ┌────────────────────────────────────────────────────────┐  │
│  │  AI Agent Context                                      │  │
│  │                                                        │  │
│  │  ┌──────────────┐  ┌──────────────┐  ┌─────────────┐ │  │
│  │  │  Built-in     │  │  MCP Server  │  │  Extension  │ │  │
│  │  │  Tools        │  │  Tools       │  │  Tools      │ │  │
│  │  │              │  │              │  │             │ │  │
│  │  │  read_file   │  │  @github/*   │  │  configure_ │ │  │
│  │  │  grep_search │  │  @azure/*    │  │  notebook   │ │  │
│  │  │  create_file │  │  @custom/*   │  │  run_task   │ │  │
│  │  │  ask_questions│  │              │  │  get_vscode │ │  │
│  │  │  manage_todo │  │              │  │  _api       │ │  │
│  │  │  runSubagent │  │              │  │             │ │  │
│  │  │  ...         │  │              │  │             │ │  │
│  │  │              │  │              │  │             │ │  │
│  │  │  EAGER LOAD  │  │ DEFERRED     │  │ DEFERRED    │ │  │
│  │  │  Always ready │  │ Need search  │  │ Need search │ │  │
│  │  └──────────────┘  └──────┬───────┘  └──────┬──────┘ │  │
│  │                           │                  │        │  │
│  │              tool_search_tool_regex           │        │  │
│  │              (discovers and loads)────────────┘        │  │
│  └────────────────────────────────────────────────────────┘  │
│                                                              │
│  ┌──────────────────┐  ┌──────────────────┐                 │
│  │  MCP Server      │  │  MCP Server      │                 │
│  │  Process (stdio) │  │  Process (SSE)   │                 │
│  │  e.g., IQPilot   │  │  e.g., GitHub    │                 │
│  └──────────────────┘  └──────────────────┘                 │
└─────────────────────────────────────────────────────────────┘

Source comparison

Aspect Built-in Tools MCP Server Tools Extension Tools
Loading Eager—always available Deferred—need tool_search_tool_regex Deferred—need tool_search_tool_regex
Provider VS Code core External processes (stdio/SSE) VS Code extensions
Examples read_file, create_file, manage_todo_list mcp_github_*, mcp_azure_*, custom servers run_task, configure_notebook, get_vscode_api
Configuration None needed .vscode/settings.json or .vscode/mcp.json Extension installation
Availability VS Code + Visual Studio VS Code only (currently) VS Code only
Customization None—fixed by VS Code Full control—you can build your own Extension developer controls

Guidelines for prompt authors

When writing prompts or agent instructions that reference specific tools:

  1. Built-in tools — Reference freely. They’re always available.
  2. MCP tools — Include tool_search_tool_regex call before first use. Mention the MCP server in your prompt context.
  3. Extension tools — Only reference if you know the extension is installed. Include a fallback strategy.
# In your prompt instructions:

## Tool Usage

Use semantic_search and grep_search for codebase analysis.
If GitHub MCP tools are available (search with tool_search_tool_regex 
for "mcp_github"), use them for issue queries.
Otherwise, fall back to fetch_webpage with the GitHub API.

📊 Token cost analysis

Every tool call consumes tokens—both for the request (function name + arguments) and the response (tool output). Understanding these costs helps you write token-efficient prompts.

Per-tool cost estimates

Tool Request Cost Typical Response Cost Total (Typical) Notes
read_file (50 lines) ~50 tokens ~500 tokens ~550 Scales linearly with line count
read_file (500 lines) ~50 tokens ~5,000 tokens ~5,050 Expensive for large reads
grep_search (20 matches) ~80 tokens ~1,500 tokens ~1,580 Compact per-match format
semantic_search (10 results) ~50 tokens ~2,000 tokens ~2,050 Variable snippet sizes
file_search ~50 tokens ~100-500 tokens ~300 Cheapest—paths only
list_dir ~30 tokens ~100-300 tokens ~200 Very cheap
create_file (100 lines) ~1,000 tokens ~50 tokens ~1,050 Cost is in output (content)
replace_string_in_file ~200-500 tokens ~50 tokens ~400 Context lines drive cost
multi_replace_string_in_file ~500-2,000 tokens ~100 tokens ~1,200 Amortizes round-trip overhead
run_in_terminal ~100 tokens ~200-10,000 tokens ~2,000 Use output filtering
get_errors ~30 tokens ~50-1,000 tokens ~300 Clean project = cheap
ask_questions ~300-500 tokens ~100 tokens ~500 Per question set
manage_todo_list ~200-500 tokens ~50 tokens ~400 Full list sent each update
runSubagent ~200 tokens ~500-2,000 tokens ~1,500 Only summary returns
tool_search_tool_regex ~50 tokens ~200-500 tokens ~350 Loads tool schemas

Expensive patterns to avoid

Pattern Cost Better Alternative
Reading entire large files ~5,000+ tokens grep_search to find relevant lines, then read_file on specific range
Sequential replace_string_in_file × 5 ~2,500 tokens Single multi_replace_string_in_file = ~1,200 tokens
Multiple semantic_search calls ~2,000 each One grep_search with regex alternation (e.g., word1\|word2\|word3)
Unfiltered run_in_terminal output ~10,000+ tokens Pipe through Select-Object -Last 20 or filter with Where-Object
read_file to scan for a string ~5,000 tokens grep_search with includePattern on the file

Cheap patterns to prefer

Pattern Why It’s Cheap
file_search before read_file Paths cost ~100 tokens; avoids reading wrong files
grep_search with includePattern Scoped search is fast and focused
list_dir for project discovery Directory names cost ~200 tokens
Parallel independent read_file calls Same total tokens, but faster wall-clock time
get_errors after edits Cheap validation; catches issues before expensive retry loops

For comprehensive token optimization across multi-agent workflows, see How to Optimize Token Consumption.


🎯 Tool selection strategy

By prompt type

Prompt Type Recommended YAML Capabilities Key Runtime Tools
Planning / Research ['codebase', 'filesystem', 'search'] semantic_search, grep_search, file_search, read_file, list_dir
Code Review ['codebase', 'search', 'problems', 'changes'] grep_search, read_file, get_errors, get_changed_files
Implementation ['codebase', 'editor', 'filesystem', 'search'] read_file, create_file, replace_string_in_file, multi_replace_string_in_file, grep_search
Documentation ['codebase', 'editor', 'filesystem', 'web_search'] semantic_search, read_file, create_file, replace_string_in_file
Testing ['codebase', 'editor', 'search', 'problems'] grep_search, read_file, create_file, run_in_terminal, get_errors
Orchestrator ['codebase', 'search'] + agent semantic_search, read_file, runSubagent, manage_todo_list
Security Audit ['codebase', 'search', 'web_search'] grep_search, read_file, semantic_search

By agent role

In multi-agent architectures, restrict tools to match each agent’s responsibilities:

# Researcher — read-only, can't modify anything
---
name: Researcher
tools: ['codebase', 'search', 'filesystem', 'fetch']
---

# Builder — can edit, can't browse the web
---
name: Builder
tools: ['codebase', 'editor', 'filesystem', 'search']
---

# Reviewer — read-only with error checking
---
name: Reviewer
tools: ['codebase', 'search', 'problems', 'changes']
---

# Orchestrator — delegates, doesn't implement
---
name: Orchestrator
tools: ['codebase', 'search', 'agent']
---

🛡️ Tool restrictions and safety

Why restrict tools?

  1. Security: Limit external network access (fetch, web_search) for internal agents
  2. Safety: Prevent unintended file modifications by read-only agents
  3. Focus: Remove irrelevant capabilities to reduce tool-calling noise
  4. Token efficiency: Fewer available tools means less schema in context

Restricting tools in agent YAML

# Security reviewer — must NOT edit files
tools: ['codebase', 'search', 'fetch']  # Excludes 'editor'

# Planner — must NOT execute commands
tools: ['codebase', 'search', 'usages']  # Excludes 'editor' and terminal

# Auditor — no external access
tools: ['codebase', 'editor', 'filesystem']  # Excludes 'fetch', 'web_search'

Terminal command boundaries

When an agent has terminal access, define explicit boundaries in its instructions:

## Terminal usage boundaries

**ALLOWED commands:**
- `npm install`, `npm run build`, `npm test`
- `dotnet build`, `dotnet test`
- `git status`, `git diff`

**NEVER execute:**
- `rm -rf`, `del /s`, or any recursive deletion
- Commands that modify system configuration
- Commands that access credentials or secrets

What you CAN’T restrict

Remember: manage_todo_list, ask_questions, runSubagent, and tool_search_tool_regex are always available regardless of the tools field. To prevent subagent usage, use the agents field instead:

# Can use runSubagent but restricted to specific agents
agents: ['researcher', 'reviewer']  # Only these subagents allowed
agents: []                          # No subagent invocation

Tool availability by platform

Capability VS Code 1.109+ Visual Studio 17.14+ GitHub CLI Copilot SDK
codebase Full Full Partial Full
editor Full Full Full Full
filesystem Full Full Full Full
fetch Full Limited Full Full
web_search Full Limited Limited Depends on model
MCP tools Full Not supported Not supported Full
runSubagent Full Not supported Not supported Full

🔧 Practical patterns

Pattern 1: Guiding tool behavior from prompt instructions

You can influence which runtime tools the model uses and how it uses them by including guidance in your prompt’s markdown body:

## Context gathering strategy

1. Start with `file_search` for `**/*.config.*` to discover configuration files
2. Use `grep_search` to find references to the target feature flag
3. Only use `read_file` on files you've confirmed are relevant (specify line ranges)
4. DON'T use `semantic_search` for this task—we need exact matches

## Editing strategy

When making changes, use `multi_replace_string_in_file` to batch all edits
rather than making sequential single-file edits.
Always run `get_errors` after editing to verify your changes compile.

This pattern bridges Level 1 (what’s available) and Level 2 (what gets used). Even if all tools are available, your prompt instructions can steer the agent toward the most efficient ones.

Pattern 2: Context-efficient file analysis

Instead of reading entire files, use a two-phase approach:

## Analysis approach

**Phase 1: Discovery** (cheap)
1. Use `list_dir` to understand project structure
2. Use `file_search` to find relevant files by name pattern
3. Use `grep_search` to find specific patterns within those files

**Phase 2: Deep read** (targeted)
4. Use `read_file` ONLY on the specific line ranges identified in Phase 1
5. Read 30-50 lines of context around each match, not the entire file

Pattern 3: Error-driven editing loop

## Implementation workflow

1. Read the target file with `read_file` to understand existing structure
2. Make changes with `replace_string_in_file` or `create_file`
3. Run `get_errors` on the modified file
4. If errors exist, fix them and re-run `get_errors`
5. Repeat until clean (max 3 iterations, then ask the user for help)

Pattern 4: Tool fallback chains

## Search strategy with fallbacks

1. Try `grep_search` with the exact function name
2. If no results, broaden with `grep_search` using regex: `functionName|related_name`
3. If still no results, use `semantic_search` with a natural language description
4. If still no results, use `list_dir` to explore the project structure manually

Pattern 5: Parallel tool execution

Independent read operations can run in parallel for faster results:

## Parallel context gathering

Read these files simultaneously:
- `read_file` on src/config.ts (lines 1-50)
- `read_file` on src/types.ts (lines 1-30)
- `grep_search` for "export interface" in src/**

Then analyze the results together before proceeding.

⚠️ Parallelism rules: Multiple read_file, grep_search, file_search, and list_dir calls can run in parallel. semantic_search cannot run in parallel with other semantic_search calls. run_in_terminal calls should never run in parallel (they share a shell session).


⚠️ Common pitfalls

Pitfall 1: Confusing Level 1 and Level 2

# ❌ Wrong: these are runtime tool names, not YAML capabilities
tools: ['read_file', 'grep_search', 'create_file']

# ✅ Correct: use capability categories
tools: ['codebase', 'editor', 'filesystem']

The tools YAML field takes capability categories (Level 1), not individual function names (Level 2).

Pitfall 2: Reading entire files

# ❌ Expensive: reads entire 500-line file (~5,000 tokens)
Read src/service.ts to find the authenticate function.

# ✅ Efficient: grep finds the line, then read the context (~600 tokens)
Use grep_search for "authenticate" in src/service.ts, 
then read_file on the matching line range.

Pitfall 3: Sequential single-file edits

# ❌ Slow and expensive: 5 separate tool calls
Replace "oldName" with "newName" in each of these 5 files.

# ✅ Efficient: single batched call
Use multi_replace_string_in_file to rename across all 5 files at once.

Pitfall 5: Unrestricted terminal access

# ❌ Dangerous: agent can run anything
---
name: Code Helper
tools: ['editor', 'codebase']  # terminal implicitly available
---

# ✅ Safer: explicit tool list, terminal boundaries in instructions
---
name: Code Helper
tools: ['editor', 'codebase', 'search']
---
Only use run_in_terminal for: npm install, npm test, dotnet build.
NEVER run destructive commands or access credentials.

Pitfall 6: Not validating after edits

# ❌ Risky: doesn't check for errors
Edit the file and move on.

# ✅ Robust: validates every change
After each edit, use get_errors to verify. 
If errors exist, fix them before proceeding.

🎯 Conclusion

Tools are the foundation of everything your prompts and agents can do. Understanding the two-level architecture—YAML capability declarations that gate runtime function calls—gives you precise control over agent behavior.

Key takeaways:

  • Level 1 (YAML) controls permissions; Level 2 (runtime) controls actions. Don’t confuse them.
  • Search tools are your most-used category. Use the decision tree: concepts → semantic_search, exact strings → grep_search, file names → file_search, known content → read_file with line ranges.
  • Edit tools should be batched with multi_replace_string_in_file when possible, and always validated with get_errors afterward.
  • Interaction tools (ask_questions, manage_todo_list) are always available and cost-effective for improving reliability.
  • Delegation tools (runSubagent) are key for orchestration—covered in depth in the subagent orchestrations article.
  • Token costs matter. Prefer grep_search + targeted read_file over reading entire files. Batch edits. Filter terminal output.
  • Restrict tools by agent role to improve safety, focus, and token efficiency.

With this foundation, you’re ready to build orchestrations where each agent has exactly the tools it needs—no more, no less. The next article, How to Design Orchestrator Prompts, uses these tools as building blocks for multi-agent coordination.

Series navigation:


📚 References

📘 GitHub Copilot Chat Tools — VS Code Documentation 📘 [Official]
Primary reference for tool configuration in VS Code. Covers the tools YAML field, tool sets, MCP tool references, and platform support. Essential reading for Level 1 configuration.

📘 VS Code Chat Subagents Documentation 📘 [Official]
Official documentation for the runSubagent tool and custom agents as subagents. Covers user-invokable, disable-model-invocation, and the agents array.

📘 Model Context Protocol Specification 📘 [Official]
The formal specification for MCP tools, resources, and transport protocols. Required reading for building custom MCP servers.

📘 VS Code MCP Server Configuration 📘 [Official]
How to configure MCP servers in VS Code settings and workspace files. Covers stdio and SSE transports, authentication, and server management.

📗 GitHub Copilot Customization — Custom Instructions 📗 [Verified Community]
GitHub’s documentation for custom instructions, prompts, and agent files. Cross-reference for how tool configuration fits into the broader customization system.

📙 How to Create MCP Servers for Copilot [Internal]
Series article covering MCP server development—the supply side of tools. Read this to understand how custom tools are built and registered.

📙 How to Structure Content for Agent Files [Internal]
Series article covering agent YAML configuration, including the tools field, agents field for subagent restrictions, and tool priority ordering.

📙 How to Design Subagent Orchestrations [Internal]
Series article with deep coverage of the runSubagent tool, coordinator/worker patterns, and context isolation mechanics.