Andes.Extensions.AI 0.3.1

dotnet add package Andes.Extensions.AI --version 0.3.1
                    
NuGet\Install-Package Andes.Extensions.AI -Version 0.3.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Andes.Extensions.AI" Version="0.3.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Andes.Extensions.AI" Version="0.3.1" />
                    
Directory.Packages.props
<PackageReference Include="Andes.Extensions.AI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Andes.Extensions.AI --version 0.3.1
                    
#r "nuget: Andes.Extensions.AI, 0.3.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Andes.Extensions.AI@0.3.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Andes.Extensions.AI&version=0.3.1
                    
Install as a Cake Addin
#tool nuget:?package=Andes.Extensions.AI&version=0.3.1
                    
Install as a Cake Tool

Andes.Extensions.AI

Middleware extensions for Microsoft.Extensions.AI: per-request and per-tool token usage tracking, and streaming status propagation for IChatClient pipelines.

Add one line to your pipeline and get:

  • Token usage tracking — input/output/total tokens for the main assistant, per model turn, and attributed to each tool call (including LLM calls nested inside tools), rolled up into a ChatUsageReport.
  • Streaming progress statuses — synthetic ChatProgressContent updates interleaved into the live stream so your UI can show "Calling GetWeather Tool", sub-statuses reported from inside the tool ("Extracting…", "Processing…"), and completion — while the model and tools are still working.
  • Out-of-band observers — implement IChatProgressObserver to receive the same events and the final report without parsing the stream.
  • Privacy by default — progress events never carry prompt content, tool arguments, or tool results unless explicitly opted in.

Install

dotnet add package Andes.Extensions.AI

Quickstart

Register the middleware before UseFunctionInvocation() — the tracker must wrap the tools that the function-invoking client executes:

using Andes.Extensions.AI;
using Microsoft.Extensions.AI;

IChatClient client = innerClient          // any IChatClient (Azure OpenAI, OpenAI, Ollama, ...)
    .AsBuilder()
    .UseToolTracking()
    .UseFunctionInvocation()
    .Build();

AIFunction weather = AIFunctionFactory.Create(
    (string city) =>
    {
        ChatProgress.Report("Extracting...");   // sub-status under "Calling GetWeather Tool"
        return $"Sunny in {city}";
    },
    "GetWeather");

await foreach (var update in client.GetStreamingResponseAsync(
    "What's the weather in Quito?",
    new ChatOptions { Tools = [weather] }))
{
    foreach (var content in update.Contents)
    {
        switch (content)
        {
            case ChatProgressContent progress:
                Console.WriteLine($"[{progress.Progress.Kind}] {progress.Progress.Message}");
                break;
            case UsageReportContent usage:
                Console.WriteLine($"Total tokens: {usage.Report.TotalUsage.TotalTokenCount}");
                break;
        }
    }

    Console.Write(update.Text);
}

Tools that are themselves LLM-backed (for example, agents exposed as functions) can attribute their own usage to the calling scope with ChatProgress.ReportUsage(...) — or simply run their own UseToolTracking() pipeline, whose total rolls up automatically.

Before persisting responses into conversation history, remove the synthetic content:

ChatResponse response = updates.ToChatResponse().StripProgressContent();

MCP tools

First-class MCP support ships as a satellite package, Andes.Extensions.AI.Mcp, so the core stays dependency-lean:

dotnet add package Andes.Extensions.AI.Mcp

McpClientTool instances classify as ToolKind.McpTool and render as "Calling {Server} MCP", and the server's progress notifications are bridged into ToolProgress updates with numeric Progress/ProgressTotal values:

IList<McpClientTool> mcpTools = await mcpClient.ListToolsAsync();

IChatClient client = innerClient
    .AsBuilder()
    .UseToolTracking(options => options.UseMcpToolClassification())
    .UseFunctionInvocation()
    .Build();

var chatOptions = new ChatOptions { Tools = mcpTools.WithTracking(mcpClient) };

See MCP support for details.

Agent tools

Microsoft Agent Framework agents run as tracked tools through their own satellite package, Andes.Extensions.AI.Agent:

dotnet add package Andes.Extensions.AI.Agent

Agents wrapped with WithTracking() classify as ToolKind.Agent and render as "Calling {Agent} Agent", and each run's AgentResponse.Usage is attributed to the calling tool's scope — a plain agent.AsAIFunction() exposes neither:

AIAgent weatherAgent = weatherChatClient.AsAIAgent(
    instructions: "You answer questions about the weather.",
    name: "Weather Agent",
    tools: [AIFunctionFactory.Create(GetWeather)]);

IChatClient client = innerClient
    .AsBuilder()
    .UseToolTracking(options => options.UseAgentToolClassification())
    .UseFunctionInvocation()
    .Build();

var chatOptions = new ChatOptions { Tools = [weatherAgent.WithTracking()] };

Agents nest (v0.3): a WithTracking-wrapped agent used as a tool of another agent — or invoked directly inside a tool body — opens its own child scope, rendering live as a child activity card with its own statuses, duration, and token usage in the report:

✓ Research Agent  agent  6.0s · 1,317 tok
  ├── Calling SearchNotes Tool
  ├── Searching notes…
  ├── Calling Packing_Agent Tool
  └── ✓ Packing Agent  agent  2.4s · 504 tok
      └── Checking essentials…

The same applies to nested MCP tools, and any tool can give a sub-operation its own child card with ChatProgress.BeginToolScope(new ToolDescriptor { ... }).

See Agent support for details.

UI

A serializable status contract for streaming progress to a UI ships as its own satellite package, Andes.Extensions.AI.UI — a matching C# and TypeScript shape, so a Blazor app and a SPA render the same activity tree from the same JSON:

dotnet add package Andes.Extensions.AI.UI

Stream AssistantStatusSnapshot instead of parsing ChatResponseUpdate yourself. Each activity carries a clean DisplayName plus a separate Kind badge — never a composed "Calling … MCP/Agent/Tool" string, so the kind word is never repeated:

await foreach (AssistantStatusSnapshot snapshot in client
    .GetStreamingResponseAsync("prompt", chatOptions)
    .ToStatusSnapshotsAsync())
{
    foreach (AssistantActivity activity in snapshot.Activities)
    {
        Console.WriteLine($"{activity.DisplayName} [{activity.Kind}] — {activity.State}");
    }
}

For an HTTP surface, stream ToUiEventsAsync() instead and serialize each event with the package's AssistantUiJsonContext over server-sent events; a browser or Blazor client folds them with the shipped TypeScript foldAssistantEvents or the C# AssistantStatusReducer. See UI support for details.

Samples

samples/Andes.Extensions.AI.Demo is an interactive console chat that exercises all four packages in one tracked pipeline and renders live activity — function/MCP/agent cards, progress bars, token usage — Claude-Code-style with Spectre.Console:

cp samples/Andes.Extensions.AI.Demo/appsettings.sample.json samples/Andes.Extensions.AI.Demo/appsettings.json
# fill in the AzureOpenAI section, then:
dotnet run --project samples/Andes.Extensions.AI.Demo

See the sample README for what each file demonstrates.

Documentation

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Andes.Extensions.AI:

Package Downloads
Andes.Extensions.AI.Agent

Microsoft Agent Framework support for Andes.Extensions.AI tool tracking: classifies agents exposed as function tools as agent tools ("Calling {Agent} Agent"), attributes each agent run's token usage to the calling tool's scope, and optionally reports the agent's own function invocations as progress statuses.

Andes.Extensions.AI.Mcp

Model Context Protocol (MCP) support for Andes.Extensions.AI tool tracking: classifies McpClientTool instances as MCP tools ("Calling {Server} MCP") and bridges MCP progress notifications into chat progress updates with numeric progress values.

Andes.Extensions.AI.UI

UI status contract for Andes.Extensions.AI tool tracking: serializable records (and a matching TypeScript interface) that project the tracked chat stream into an assistant-activity hierarchy — the assistant's own functions, MCP tools, and agents, each with sub-statuses, nested children, and token usage — for rendering live progress in Blazor, a console, or any TypeScript SPA.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.1 0 7/29/2026
0.3.0 35 7/29/2026
0.2.0 75 7/25/2026