Skip to content

.NET: UseAIContextProviders accumulates context provider tools in ChatOptions.Tools across calls #4864

Description

Bug Description

UseAIContextProviders merges AIContext.Tools from context providers (e.g., FileAgentSkillsProvider) into ChatOptions.Tools on every API call, but never clears previously injected tools. When ChatOptions.Tools is a shared mutable list reference, tools from context providers accumulate across calls.

Steps to Reproduce

  1. Register a FileAgentSkillsProvider via UseAIContextProviders
  2. Pass a List<AITool> to ChatOptions.Tools (shared reference)
  3. Make multiple API calls through the agent

After the first call, ChatOptions.Tools contains load_skill and read_skill_resource (injected by the provider). After the second call, it contains two copies of each. After N calls, N copies.

Impact

  • Anthropic API rejects the request with HTTP 400: "tools: Tool names must be unique."
  • OpenAI API silently accepts duplicates, so the bug goes unnoticed there
  • The tool list grows unboundedly across calls, wasting tokens

Expected Behavior

Context provider tools should be merged into a per-request copy of ChatOptions.Tools, not into the original shared list. The original list should remain unmodified so subsequent calls start from a clean baseline.

Workaround

We reset ChatOptions.Tools to a fresh snapshot of our baseline tool list before each call in a DelegatingChatClient, so the framework's merge always starts clean:

// In a DelegatingChatClient sitting before UseAIContextProviders in the pipeline
private void ResetToolsFromBaseline(ChatOptions? options)
{
    if (options is null) return;
    options.Tools = new List<AITool>(baseline);
}

Environment

  • Microsoft.Agents.AI v1.0.0-rc4
  • Provider: Anthropic (Claude) via Microsoft.Extensions.AI
  • .NET 10

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

.NETUsage: [Issues, PRs], Target: .NetbugUsage: [Issues], Target: all issues (Legacy, prefer issue type: bug)triageUsage: [Issues], Target: All issues that still need to be triaged

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions