#2745·ag-ui

.NET: Make server-side tool calls private by default

Author: danroth27Created Sep 13, 2026Updated Sep 13, 2026

Pre-flight Checklist

  • I have searched existing issues and this hasn't been requested yet.

Problem or Motivation

The current AG-UI design exposes all server-side tool calls in the client-visible event stream. When an agent invokes a server tool, its name and arguments are sent over the wire using TOOL_CALL_START, TOOL_CALL_ARGS, and TOOL_CALL_END.

This makes sense when a server tool intentionally participates in the UI, but many server tools are implementation details: database lookups, internal service calls, routing operations, retries, and agent-to-agent orchestration.

The existing public-by-default behavior has several consequences:

  • Internal implementation details unintentionally become part of the application's public protocol contract.
  • Tool arguments may contain data that should not cross the client trust boundary.
  • Refactoring or renaming an internal tool can affect clients observing the stream.
  • Tool arguments can be duplicated when the call is also projected into state, activity, or custom events.
  • Applications need custom filtering simply to preserve a conventional server/client boundary.

Client-side filtering is insufficient because the information has already crossed the wire. Suppressing calls in the underlying agent framework is also undesirable because it may need the complete tool lifecycle for execution, model continuation, persistence, and tracing.

This issue proposes changing the existing design: server-side tool calls should be private by default and exposed only through explicit server configuration.

Proposed Solution

AG-UI server adapters should apply an explicit visibility policy when converting server-side agent events into AG-UI events.

The proposed default is:

Server tool classification Wire visibility
Explicitly exposed or observable Public
Not explicitly exposed Private

A private server tool should continue to execute normally:

model requests server tool
-> server executes tool
-> result returned to model
-> model continues

But the AG-UI adapter should not emit its client-visible lifecycle:

  • TOOL_CALL_START
  • TOOL_CALL_ARGS
  • TOOL_CALL_END
  • Associated tool-result content

Applications should explicitly expose server tools whose lifecycle is intentionally part of the UI:

csharp
options.ExposeTool("web_search");
options.ExposeTool("generate_report");

For applications that intentionally present most server tool activity, SDKs should also provide a convenience API that exposes all tools while allowing specific internal tools to be excluded:

csharp
options
    .ExposeAllTools()
    .HideTool("lookup_customer_record")
    .HideTool("internal_route");

An equivalent overload could accept exclusions directly:

csharp
options.ExposeAllTools(
    except:
    [
        "lookup_customer_record",
        "internal_route",
    ]);

SDKs could additionally support predicate-based configuration where idiomatic:

csharp
options.ExposeTools(tool =>
    !tool.Name.StartsWith("internal_", StringComparison.Ordinal));

The important semantics are:

  • Server tools remain private unless explicitly exposed.
  • ExposeTool exposes an individual tool.
  • ExposeAllTools is an explicit opt-in to the current public behavior.
  • A specific exclusion always overrides the expose-all setting.
  • Hiding a tool suppresses its call arguments and associated result content consistently.

Applications should also be able to project a private operation into a safer public abstraction without exposing the underlying tool:

private lookup_customer_record tool
-> server executes tool
-> tool call and result remain private
-> sanitized STATE_SNAPSHOT or activity event emitted

The protocol may not require a new wire-level field because private calls are never transmitted. However, the specification should define this visibility boundary, and server SDKs should provide an idiomatic per-tool configuration mechanism.

Existing Behavior and Compatibility

This is a proposed change from the current public-by-default behavior for server tools.

Existing applications may depend on observing all server tool calls for status displays, debugging, or generative UI. A transition strategy may therefore be necessary:

  1. Introduce private-by-default behavior as an opt-in policy.
  2. Provide migration guidance for explicitly exposing UI-relevant server tools.
  3. Change the default in the next major protocol or SDK version.
  4. Retain ExposeAllTools() as a compatibility option for the current behavior.

Existing applications could preserve today's behavior with:

csharp
options.ExposeAllTools();

They could then selectively hide sensitive or implementation-specific tools:

csharp
options
    .ExposeAllTools()
    .HideTool("lookup_customer_record");

The long-term default should follow least disclosure: registering a server tool for model use should not implicitly publish that tool to every AG-UI client.

Alternatives Considered

Continue exposing every server tool and let the client ignore internal ones. This does not establish a meaningful trust boundary because the information still crosses the wire.

Filter calls in the client. This is too late to prevent information disclosure or accidental client dependencies.

Suppress calls in the underlying agent framework. This conflates internal execution with public protocol projection and may interfere with execution, continuation, tracing, persistence, or other consumers.

Require custom server-side wrappers. This is difficult to implement correctly across streamed arguments, parallel calls, call/result correlation, and continuation runs. Visibility should be a first-class AG-UI server policy.

Additional Context

The intended responsibility split is:

Agent framework
    -> retains the complete internal execution stream

AG-UI server adapter
    -> keeps server tools private by default
    -> exposes only explicitly public server tools
    -> may project internal operations into sanitized public events

AG-UI client
    -> receives only server operations intended to be part of the UI contract

This preserves AG-UI's transparent tool experiences where they are intentional without automatically making every server-side implementation detail part of the public protocol stream.