Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
158714 stories
·
33 followers

Built-In Observability for Serverless AI Agents on Azure Functions

1 Share

Azure Functions Agents - the markdown-first runtime that turns a folder of *.agent.md files into a serverless Azure Functions app - now ships with OpenTelemetry tracing built into the runtime itself. Every agent run becomes a real, structured trace in Application Insights: the model used, the session, and every tool call or sub-agent hand-off along the way. None of it requires writing a line of telemetry code in your app.

Click here to create and run a Serverless Agent using Azure Functions

Full visibility, zero code

Bootstrapping an agent app is still two lines:

from azure_functions_agents import create_function_app app = create_function_app()

Turning on export is two settings, no code:

In requirements.txt - 

pip install azurefunctions-agents-runtime[monitor]
In your App Settings -
APPLICATIONINSIGHTS_CONNECTION_STRING=<your-app-insights-connection-string></your-app-insights-connection-string>
 

From there, every run shows up automatically in Application Insights' Agents view, tagged with a consistent set of attributes the runtime adds for you: which agent ran, which model answered, which tools it called, and how the run finished. You don't pick and choose what to instrument - you get the whole run, every time, the same way, regardless of what the agent is doing underneath.

That consistency is what makes the tracing useful for more than debugging. It's also the simplest way to see something that would otherwise happen invisibly inside a single API call.

Example: watching a model decision happen in real time

One good illustration is Model Router - a model you deploy yourself in your Foundry resource, like any other model deployment. Point an agent's model setting at that deployment, and Model Router picks a different underlying LLM per prompt: a smaller model for simple requests, a larger one once a prompt actually needs it.

Normally that choice is invisible - it happens inside one API call. But because Azure Functions Agents traces every run the same way no matter which model is behind it, the decision shows up for free. Same chat session, two prompts:

Prompt

Model Router picked

Why

Easy, one-shot question

gpt-5-mini

Small model is comparable quality for a fraction of the cost.

Complex, multi-step reasoning

gpt-5.4

Router escalates to a larger model once the prompt needs it.

Both requests show gen_ai.request.model = model-router, that's the deployment the agent called. What changes per message is the response attribute, which names whichever model Router actually picked.

 

 

Trace for the easy prompt (response model gpt-5-mini)

 

 

Trace for the hard prompt (response model gpt-5.4)

 

Full session in the Agents pane of Application Insights

 

Nothing here was instrumented specifically for Model Router - this is just what a trace looks like now, for any agent, on any model.

Try it yourself

  1. Add the two settings above to an existing agent app - no code changes needed.
  2. Send a request or two, then open Application Insights' Agents view (or Transaction Search).
  3. Look at what's already there: model, session, tool calls, and timing, all correlated under one trace.

Wrapping up

The point isn't any single scenario - it's that whatever you build next on Azure Functions Agents, from a simple single-model agent to something as dynamic as router-based model selection, you'll be able to see exactly what happened without adding anything yourself. Try it against your own agent and see what's already there.

Resources

Read the whole story
alvinashcraft
just a second ago
reply
Pennsylvania, USA
Share this story
Delete

AWS Tools Installer V2 is Now Generally Available

1 Share

If you’ve been managing multiple AWS Tools for PowerShell modules individually, you know how time-consuming installations and updates can be. In this post, we announce the general availability of AWS Tools Installer V2. It minimizes installation time by downloading a single zip file and extracting modules in parallel.

In February 2026, we announced the preview of AWS Tools Installer V2.

V2 improvements

AWS Tools Installer V2 downloads a single zip file from Amazon CloudFront and extracts modules in parallel. This eliminates the need to install hundreds of individually packaged modules.

Installer V2 installs modules by default, so commands are available for immediate use. This also helps avoid module import conflicts that can occur when modules are not all on the same version.

The following example shows how to install all AWS Tools for PowerShell modules by running Install-AWSToolsModule. To reduce the risk of breaking changes, add the -Version parameter. It limits updates to minor versions of V5 of AWS Tools for PowerShell.

Install-AWSToolsModule -Version 5.*

AWS Tools Installer V2 also introduces the self-update commands Install-AWSToolsInstaller and Uninstall-AWSToolsInstaller so you can update the installer module directly without manual steps.

The following example installs the latest minor version updates for AWS Tools Installer V2. Staying on minor versions helps you maintain a stable environment.

Install-AWSToolsInstaller -Version 2.*

Bugs fixed

V2 resolves two key issues:

  1. Previously, latest modules were not installed on systems with discontinued modules. V2 now successfully updates modules that are not discontinued.
  2. During the daily release window, installations sometimes failed because some modules were still being published. V2 avoids this by installing only the module versions that have completed publishing.

New features

  1. Support for Offline Installation: The new -SourceZipPath parameter allows installation from locally staged files in offline or air-gapped environments.
  2. Support for Prerelease Installation: A new parameter called -Prerelease allows installation of preview builds of AWS Tools for PowerShell and AWS Tools Installer.
  3. Installer Update Notifications: When you import AWS Tools Installer, it displays a message notifying you if a new version is available.
  4. Support for Standard Module Removal: AWS Tools Installer now adds metadata so you can remove modules using standard PowerShell commands (Uninstall-Module and Uninstall-PSResource).
  5. Removal of Legacy Modules: AWS Tools Installer V2 supports uninstalling the legacy AWSPowerShell and AWSPowerShell.NetCore modules from the paths listed in the PSModulePath environment variable.
Uninstall-AWSToolsModule -CleanUpLegacyScope 'CurrentUser'
Install-AWSToolsModule -CleanUpLegacyScope 'CurrentUser'

Breaking changes

You must plan for the following potential issues when upgrading:

  1. New download endpoint: AWS Tools Installer V2 uses following endpoint to download zip files: https://sdk-for-net.amazonwebservices.com/ps/. You might need to update your firewall rules to allow access to this endpoint.
  2. Proxy parameters ignored: The -Proxy and -ProxyCredential parameters are now ignored and have no effect. They are still accepted for backward compatibility. To configure proxy settings for your environment, see the PowerShell environment variables documentation. On Windows PowerShell 5.1, downloads use your system proxy settings.
  3. Force parameter behavior change: The -Force parameter is now deprecated and ignored for Uninstall-AWSToolsModule. When running Install-AWSToolsModule -Force, the existing module is overwritten even if the name and version match. To skip interactive confirmation prompts, add -Confirm:$false to the command.
  4. Ignored parameters: The -SkipUpdate, -SkipPublisherCheck, and -AllowClobber parameters are accepted for backward compatibility but no longer have any effect. If your scripts relied on -SkipUpdate to prevent updates, installed modules will now be updated.

Note: The original V1 command behavior is preserved in these additional commands: Install-AWSToolsModuleV1, Uninstall-AWSToolsModuleV1, and Update-AWSToolsModuleV1. You can define an alias for each command to map legacy scripts back to the original functionality after upgrading to V2. For example:

Set-Alias -Name Install-AWSToolsModule -Value Install-AWSToolsModuleV1

Getting started

For prerequisites and full setup details, see Installing the AWS Tools for PowerShell.

Install the latest version of AWS Tools Installer V2 from the PowerShell Gallery (PSGallery) by running the following command:

Install-Module -Name AWS.Tools.Installer -MinimumVersion 2.0.0 -MaximumVersion 2.9.999 -Repository PSGallery

View help documentation

Once installed, run the following command to list the available AWS Tools Installer commands:

Get-Command -Module AWS.Tools.Installer

Run Get-Help to view documentation for any AWS Tools Installer command. For example:

Get-Help Install-AWSToolsModule -Full

Conclusion

AWS Tools Installer V2 is now generally available with faster installation, parallel extraction, and improved reliability. To get started, install V2 from PSGallery using the commands in this post.

Provide feedback

We’re looking forward to hearing what you think about the new version of AWS Tools Installer. Please share any feedback you have at the AWS Tools for PowerShell GitHub repository.

Read the whole story
alvinashcraft
17 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

SwiftDotNet — It Started With "What If I Could Just Write SwiftUI in C#?"

1 Share
A shower thought about writing SwiftUI from C# turned into a Kotlin shim for Jetpack Compose, and then into the realization that the shim was never the point. One C# view tree, a diff engine, and a patch protocol — now rendering as real SwiftUI, real Compose, real GTK4, real WinUI, real DOM, and a from-scratch SkiaSharp toolkit that paints the whole thing itself. Plus 28 real controls built on it, what writing your own looks like on each backend, and an honest accounting of how far the Skia renderers still have to go. Think .NET Comet, but without the MAUI underneath it.
Read the whole story
alvinashcraft
39 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Remove Is Not Uninstall

1 Share

Just as https://devblogs.microsoft.com/insidemsix/there-is-no-install-its-stage-and-register/ explained that Install is not truly an installation operation in MSIX, Remove is similarly not an uninstall operation.

This can be surprising – sometimes even alarming – to developers coming from traditional installer technologies such as MSI, where uninstalling software typically implies:

  • binaries are deleted
  • directories are removed
  • registry entries are cleaned
  • runtime artifacts are purged

In MSIX, that model simply does not exist.

Remove = Deregister + (Maybe) Destage

From MSIX Deployment’s perspective, a package lifecycle consists of four fundamental operations:

  • Stage – acquire and securely place the payload on disk
  • Register – associate the package with a user
  • Deregister – remove the package association for a user
  • Destage – remove the package payload from disk

There’s a symmetry here. Stage and Register do the work necessary to make a package available for use. Deregister and Destage unwind that work, first removing the package from use and ultimately removing it from the system.

Interestingly, the deployment API doesn’t provide DeregisterPackageAsync() or DestagePackageAsync(). Instead, there is only RemovePackage*Async()1.

“Remove” is the public abstraction over unwinding a package’s lifecycle, as far as the system can safely go.

There is no ForceTargetApplicationShutdown option for Remove*() APIs. Instead, remove operations effectively behave as though the option existed and is always enabled. Running processes using the package may be shut down or terminated so the servicing operation can proceed.

If the package is no longer in use, Deployment deregisters it and, when appropriate, destages it.

When appropriate.

Deregistration Is Guaranteed, Destaging Is Conditional

A package removal operation does not necessarily delete the package payload from disk.

Instead, the operation primarily focuses on removing the package’s registrations and system integrations:

  • removing user-specific registrations
  • disconnecting Start Menu entries
  • revoking file type associations
  • updating runtime metadata
  • releasing MSIX-managed application data
  • deleting an internal reference to the package
  • destaging the package IF no remaining references exist

From the user’s perspective, the application is gone.

From the operating system’s perspective, however, the package may still be present on disk—available for, and possibly in use by, other users.

That distinction is crucial to understanding why Remove is not the same thing as Uninstall.

Remove always unwinds registrations. Deletion of the package payload is conditional.

But if we’ve just deregistered the package, what references are left?

As it turns out, quite a few.

That’s a tale for Part 2…


1 Remove comes in several variants, including PackageManager‘s RemovePackageAsync() and PackageDeploymentManager‘s RemovePackageByFamilyNameAsync(). These provide variations of scoping what to remove, but otherwise their functionality is the same.

The post Remove Is Not Uninstall appeared first on Inside MSIX.

Read the whole story
alvinashcraft
46 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

MBW 1036: Corn Is Just Corn - Apple's Q3 2026 Results

1 Share

Apple's Q3 2026 results are in, with the company's total revenue up by 16% from the year-ago quarter! Apple's Rosetta software tool is further nearing its end-of-life. And OpenAI rebuts Apple's trade secrets allegations.

  • Apple announces record Q3 results.
  • Apple stock opens down roughly 10% following mixed Q3 2026 results.
  • Siri AI could come with a paywall for power users.
  • First Apple Silicon-native CrossOver build in testing as Rosetta's end nears.
  • What's the catch with the Apple Upgrade program?
  • OpenAI rebuts Apple trade secrets allegations in new response with receipts.
  • From OpenAI: "Apple is getting this wrong"
  • Apple Photos' facial features prompt a $32.5B class-action lawsuit.

Picks of the Week

  • Andy's Pick: Infuse Media Player
  • Jason's Pick: Overcast
  • Mikah's Pick: Pelican Marine Waterproof Phone Pouch

Hosts: Mikah Sargent, Andy Ihnatko, and Jason Snell

Download or subscribe to MacBreak Weekly at https://twit.tv/shows/macbreak-weekly.

Join Club TWiT for Ad-Free Podcasts!
Support what you love and get ad-free audio and video feeds, a members-only Discord, and exclusive content. Join today: https://twit.tv/clubtwit

Sponsors:





Download audio: https://pdst.fm/e/pscrb.fm/rss/p/mgln.ai/e/294/cdn.twit.tv/megaphone/mbw_1036/ARML3331673094.mp3
Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

Beyond Chat: live Speech-to-Text with Foundry Local and C#

1 Share

A year ago, I wrote a .NET Blog post about running GPT-OSS locally with Ollama and C#. That sample used IChatClient from Microsoft.Extensions.AI to build one of the most familiar Local AI scenarios: a chat application.

Chat is a great place to start, but Local AI is not limited to asking a small language model to write a poem or summarize a document.

Foundry Local can also run specialized models for workloads such as speech recognition. Even better, it manages the complete model lifecycle for your application: finding the appropriate model variant, downloading it when required, storing it in its local cache, loading it for inference, and unloading it when the application is finished.

In this post, we will build a small C# console application that uses an NVIDIA 0.6B Nemotron speech model to transcribe microphone audio in real time. The model runs locally, and the application receives partial and final transcription results while you speak.

Abstractions when possible, native capabilities when needed

In the previous Ollama sample, Microsoft.Extensions.AI gave us the IChatClient abstraction. That makes it possible to write chat code that can work with different AI providers without changing the application’s core logic.

Live audio streaming is slightly different. The AudioClient used in this sample belongs to the native Microsoft.AI.Foundry.Local SDK; it is not a Microsoft.Extensions.AI abstraction. We use the provider SDK here because live transcription sessions, raw PCM streaming, and interim results are Foundry Local specific capabilities.

This is a useful pattern for .NET AI applications:

  • Use Microsoft.Extensions.AI abstractions when they match the scenario.
  • Use the provider SDK when you need a specialized provider capability.

The two approaches complement each other.

What we are building

The application has a simple flow:

  1. Initialize Foundry Local and resolve a speech model from its catalog.
  2. Download and load the model.
  3. Create a live transcription session.
  4. Capture microphone audio as 16-kHz, 16-bit, mono PCM.
  5. Stream the audio to the model and print interim and final results.

Diagram showing speech-to-text flow

The complete sample targets .NET 10 and uses:

  • Microsoft.AI.Foundry.Local.WinML for Foundry Local.
  • NAudio to capture microphone audio.
  • nemotron-speech-streaming-en-0.6b, an English streaming ASR model from the Foundry Local catalog.

Important

This sample is Windows-only. Microsoft.AI.Foundry.Local.WinML targets Windows ML, and NAudio.WaveInEvent uses the Windows audio APIs.

You can find the complete working application here:

https://github.com/microsoft/Generative-AI-for-beginners-dotnet/tree/main/samples/CoreSamples/11-foundrylocal-live-transcription

See it in action

I show the complete application running on the .NET & AI Community Standup: Foundry Local resolves and loads the speech model, the application captures microphone audio, and interim and final transcription results appear in real time.

▶ Watch the .NET & AI Community Standup

Let Foundry Local manage the model

The first important part is resolving the model through the Foundry Local catalog:

About the code snippets

The snippets in this post focus on the Foundry Local APIs and omit some application-level details for clarity. See the complete working sample for the full implementation, including error handling and resource cleanup.

using Microsoft.AI.Foundry.Local;
using Microsoft.Extensions.Logging.Abstractions;
using NAudio.Wave;
using System.Threading.Channels;

var config = new Configuration
{
    AppName = "dotnet-local-ai-live-transcription",
    LogLevel = LogLevel.Information
};

await FoundryLocalManager.CreateAsync(config, NullLogger.Instance);

using var manager = FoundryLocalManager.Instance;
await manager.DownloadAndRegisterEpsAsync(); // EPs: execution providers for the detected hardware  

var catalog = await manager.GetCatalogAsync();
var model = await catalog.GetModelAsync(
    "nemotron-speech-streaming-en-0.6b")
    ?? throw new InvalidOperationException("Speech model not found.");

await model.DownloadAsync(progress =>
    Console.Write($"\rDownloading model: {progress:F2}%"));

await model.LoadAsync();

This is one of my favorite parts of the Foundry Local developer experience. The application asks for a model by alias, and Foundry Local takes care of the model files and the execution providers required by the available hardware.

On the first run, the model and the necessary execution providers are downloaded. If you keep the model in the Foundry Local cache, later runs can reuse it without downloading it again. There is no separate download script, no manually managed model folder, and no API key.

On the first run, Foundry Local downloads and caches the Nemotron speech model before starting the application.

Foundry Local also owns the catalog-specific metadata and file layout. For this scenario, the model should be obtained from the catalog and downloaded through model.DownloadAsync() instead of downloading the files separately from Hugging Face.

Foundry Local can select the model variant and execution provider that match the available hardware. That is a useful reminder that not every Local AI workload needs a large model or even a GPU.

Create a live transcription session

Once the model is loaded, we can get its AudioClient and create a streaming session:

var audioClient = await model.GetAudioClientAsync();
using var session = audioClient.CreateLiveTranscriptionSession();

session.Settings.SampleRate = 16000;
session.Settings.Channels = 1;
session.Settings.Language = "en"; // this Nemotron variant is English-only  

await session.StartAsync();

This is not batch transcription over a completed audio file. The session stays open and accepts raw PCM audio while the user is speaking.

The sample uses NAudio.WaveInEvent to capture the microphone at 16 kHz, 16 bits, and one channel. Because the NAudio callback is synchronous and session.AppendAsync() is asynchronous, the complete sample places audio chunks in a bounded channel and sends them to the session from a dedicated task. This respects backpressure and avoids creating an unlimited number of fire-and-forget operations.

The essential operation that feeds the model is:

var audioChannel = Channel.CreateBounded<byte[]>(new BoundedChannelOptions(50)
{
    FullMode = BoundedChannelFullMode.DropOldest
});

var appendTask = Task.Run(async () =>
{
    await foreach (var chunk in audioChannel.Reader.ReadAllAsync())
    {
        await session.AppendAsync(chunk);
    }
});

Read partial and final results as an async stream

The transcription results arrive through an async stream. Consume it from a different task than the one calling AppendAsync(), so that reading results never blocks audio capture:

await foreach (var result in session.GetStream())
{
    var text = result.Content?[0]?.Text;

    if (result.IsFinal)
    {
        Console.WriteLine();
        Console.WriteLine($"[FINAL] {text}");
    }
    else if (!string.IsNullOrEmpty(text))
    {
        Console.Write(text);
    }
}

Interim results can be displayed immediately while the user speaks. When the model completes an utterance, it emits a final result. This makes the API useful for experiences such as live captions, meeting notes, voice-controlled desktop applications, accessibility tools, and edge solutions with limited connectivity.

Here is the application already running, with the model loaded and live transcription active:

Console showing cyan interim and white final speech-to-text output beside a GPU monitor.

The application displays interim transcription in cyan and finalized text in white with the [FINAL] prefix.

The snippets above focus on each stage of the application. In the complete sample, resource cleanup is protected so it also runs after an exception. The simplified lifecycle looks like this:

await model.LoadAsync();
try
{
  using var session = audioClient.CreateLiveTranscriptionSession();
  await session.StartAsync();

  try
  {
    using var waveIn = new WaveInEvent();
    // Capture and stream microphone audio.
  }
  finally
  {
    await session.StopAsync();
  }
}
finally
{
  await model.UnloadAsync();
}

The sample uses Enter for a graceful shutdown. A production command-line application that supports Ctrl+C should handle Console.CancelKeyPress, cancel the active work, and allow the same finally path to complete.

The sample also demonstrates RemoveFromCacheAsync() so you can explicitly remove the downloaded model when you no longer want to keep it. In a normal application, keeping it cached avoids downloading it again on the next run.

Why run speech-to-text locally?

Local inference brings some practical advantages to this scenario:

  • Microphone audio stays on the device.
  • No cloud AI resource or API key is required.
  • After the initial model download, inference can run without a network round trip.
  • The streaming model can run through the CPU variant selected by Foundry Local.
  • The application still uses familiar C# patterns: async/await, async streams, channels, and strongly typed SDK clients.

Local AI will not replace every cloud AI workload. Larger models, centralized management, elastic scale, and other cloud services remain important. But for privacy-sensitive audio, offline experiences, prototypes, and applications that need on-device processing, it gives .NET developers another very useful option.

Summary

Chat clients are usually the first Local AI demo and for good reason. They are easy to understand and fun to build. But Foundry Local is more than a local chat runtime.

It can manage and run different types of models, including specialized streaming speech models, directly from a C# application. You focus on the experience you want to build; Foundry Local handles much of the model lifecycle underneath it.

And yes, asking a local model to write a poem is still allowed. Now your application can also transcribe the poem while you read it.

Learn more

The post Beyond Chat: live Speech-to-Text with Foundry Local and C# appeared first on .NET Blog.

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories