🦁

OpenTelemetry 対応 - Microsoft Agent Framework (C#) その20

に公開

シリーズ記事

はじめに

今回は、最近アプリログとかトレースを収集するための標準的な仕組みになっている OpenTelemetry を Microsoft Agent Framework で使ってみようと思います。OpenTelemetry 自体は .NET でもサポートされていますし Aspire でもサポートされています。Aspire Dashboard を使うと簡単にトレースを可視化できるので便利です。

ということで、さっそくやってみましょう。

Aspire プロジェクトを作成

では Aspire 13 のプロジェクトを新規作成します。Aspire の空アプリを作成します。
そこにワーカー サービスを追加します。VS 2026 でプロジェクトを追加する際に「.NET Aspire オーケストレーションへの参加」のチェックボックスを追加することで ServiceDefaults の設定や Aspire のアプリホストプロジェクトを起動した際に一緒に起動してくれるようになります。

ワーカー サービスのプロジェクト テンプレートには、以下のようにロガーでログを出すようなコードが入っているのでダッシュボードで確認できます。

namespace AgentWorker;

public class Worker(ILogger<Worker> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            if (logger.IsEnabled(LogLevel.Information))
            {
                logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            }
            await Task.Delay(1000, stoppingToken);
        }
    }
}

実行してみましょう。以下のように Aspire Dashboard にログが表示されることが確認できます。

AppHost プロジェクトの設定

では、Agent Framework を使っていきましょう。まずは、AI を使うようにしましょう。AppHost プロジェクトに以下のパッケージを追加します。今回は GitHub Models を使うようにしたいと思います。

  • Aspire.Hosting.GitHub.Models

そして、AppHost プロジェクトの AppHost.cs に GitHubModel の追加とワーカー プロジェクトに参照を追加するコードを追加します。

AppHost.cs
using Aspire.Hosting.GitHub;

var builder = DistributedApplication.CreateBuilder(args);
// GitHub Models の追加
var chat = builder.AddGitHubModel("chat", GitHubModel.OpenAI.OpenAIGpt41);

builder.AddProject<Projects.AgentWorker>("agentworker")
    // ワーカー プロジェクトに参照を追加
    .WithReference(chat);

builder.Build().Run();

次に、GitHub Models を使うための API キーを設定します。GitHub Models の API キーは GitHub の個人アクセストークンで取得できます。今回は GPT-4.1 を使うので以下のページから Use this model からsカウ性します。

https://github.com/marketplace/models/azure-openai/gpt-4-1

取得したキーは appsettings.json やユーザーシークレットに以下のようなパラメーターを追加して設定します。

{
    "Parameters": {
        "chat-gh-apikey": "<<取得したPAT>>"
    }
}

ワーカー プロジェクトの設定

次にワーカー プロジェクトにエージェントを追加していきます。そのために Aspire で追加された GitHub Models の OpenAI の gpt-4.1 を使うためのパッケージと、Agent Framework のパッケージを追加します。

  • Aspire.OpenAI
  • Microsoft.Agents.AI
  • Microsoft.Agents.AI.OpenAI
  • Microsoft.Agents.AI.Hosting

ワーカー プロジェクトの Program.cs に以下のようにエージェントの登録コードを追加します。

Program.cs
using AgentWorker;
using Microsoft.Agents.AI.Hosting;

var builder = Host.CreateApplicationBuilder(args);

builder.AddServiceDefaults();
builder.AddOpenAIClient("chat")
    .AddChatClient();
builder.Services.AddAIAgent(
    "CatAgent",
    """
    あなたはネコ型アシスタントです。猫らしく振舞うために語尾は「にゃん」にしてください。
    挨拶をされたら、アイスブレイクとして猫に関する豆知識を一つ提供してください。
    """);
builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();

そして Worker.cs にエージェントを呼び出すコードを追加します。今回は OTel のログが出ているかを見るだけなので、適当に挨拶をするだけです。

Worker.cs
using Microsoft.Agents.AI;

namespace AgentWorker;

public class Worker([FromKeyedServices("CatAgent")]AIAgent catAgent, ILogger<Worker> logger) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            if (logger.IsEnabled(LogLevel.Information))
            {
                logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
            }

            var response = await catAgent.RunAsync("こんにちは!", cancellationToken: stoppingToken);
            logger.LogInformation("CatAgent Response: {response}", response.Text);

            await Task.Delay(1000, stoppingToken);
        }
    }
}

この状態で実行するとトレースにログが出るようになり、以下のように AI の呼出しは確認できます。

キラキラのアイコンがあるので、そこを選択すると以下のようにシステム メッセージやユーザー メッセージなどが確認できます。いい感じですね。

これは ChatClient 側でやり取りしているものが見えています。これが見えれば実質困らない気もしますが Agent Framework の側でも OpenTelemetry の機能があります。

これを有効化するには、ワーカー プロジェクトの Program.cs で AIAgent に対して OpenTelemetry のミドルウェアを追加します。

Program.cs
using AgentWorker;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

var builder = Host.CreateApplicationBuilder(args);

builder.AddServiceDefaults();
builder.AddOpenAIClient("chat")
    .AddChatClient();
// もっと良い書き方があるかもしれないけど、今みつけた DI コンテナに AIAgent を登録しつつ
// OpenTelemetry ミドルウェアを追加する方法はこの書き方
builder.AddAIAgent(
    "CatAgent",
    (sp, name) => sp.GetRequiredService<IChatClient>()
        // AIAgent を作成
        .CreateAIAgent("""
            あなたはネコ型アシスタントです。猫らしく振舞うために語尾は「にゃん」にしてください。
            挨拶をされたら、アイスブレイクとして猫に関する豆知識を一つ提供してください。
            """,
            name)
        // Builder にして OpenTelemetry ミドルウェアを追加
        .AsBuilder()
        .UseOpenTelemetry(builder.Environment.ApplicationName)
        .Build());
builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();

Aspire のプロジェクトテンプレートでは builder.Environment.ApplicationName という名前のソースに対して Exporter が構成されているので、これを指定しています。この変更をすると以下のようにキラキラアイコンのついたトレースの階層が1つ増えます。

これをクリックすると以下のようにエージェントに対する入力と出力が表示されます。

OpenTelemetry ミドルウェアを追加することで、エージェントの入出力もトレースできるようになりました。これでエージェントの動作をより詳細に追跡できるようになります。今回は OpenAI の ChatClient を使っていて、そこで可視化されるいい感じのログが出ていましたが、これは他の AIAgent の実装を使っても同様にトレースされます。例えば固定値を返す EchoAgent のような実装をした AIAgent を作成しても同様にトレースされます。

そのため、自分のアプリ内で AIAgent から ChatClient まで面倒を見ている場合は AIAgent に OpenTelemetry のミドルウェアは追加しなくてもいいかもしれません。そうではなく外部で公開されている Agent のエンドポイントを AIAgent として呼び出すケース、例えば A2AAgent などでは AIAgent に OpenTelemetry ミドルウェアを追加することでエージェントの入出力をトレースすることで、いい感じに可視化できるのではないかと思います。

Application Insights へのエクスポート

余談ですが、Application Insights に最近 Agents (Preview) という項目が追加されているので、このログを出すようにして試してみたいと思います。Aspire の ServiceDefaults では以下のように Application Insights にエクスポートする場合には、このコメントを削除してくださいと書いてある箇所があります。

ServiceDefaults.cs
private static TBuilder AddOpenTelemetryExporters<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
{
    var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]);

    if (useOtlpExporter)
    {
        builder.Services.AddOpenTelemetry().UseOtlpExporter();
    }

    // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package)
    //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]))
    //{
    //    builder.Services.AddOpenTelemetry()
    //       .UseAzureMonitor();
    //}

    return builder;
}

手順に従って ServiceDefaults のプロジェクトに以下のパッケージを追加します。

  • Azure.Monitor.OpenTelemetry.AspNetCore

他のパッケージとのバージョンの整合性に関するエラーが出た場合は、依存パッケージなどを更新したりしてバージョンを合わせてください。

そして、上記のコードのコメントを外します。UseAzureMonitor が無いというエラーが出るので using Azure.Monitor.OpenTelemetry.AspNetCore; も追加しましょう。そして Application Insights の接続文字列を appsettings.json やユーザーシークレットに以下のように追加します。

{
    "APPLICATIONINSIGHTS_CONNECTION_STRING": "<<Application Insights の接続文字列>>"
}

この状態で実行すると Application Insights の Agents (Preview) に以下のようにトレースが表示されるようになります。今回ログを送った CatAgent のデータが来ていることが確認できます。

トレースの詳細を確認すると以下のように Aspire Dashboard で確認したものと同じように Agent の入出力と LLM とのやり取りが確認できます。

本番は Azure の場合は Application Insights にログを送ることが多いと思うので、その際には、今回説明したようなひと手間を加えて Agent のログを出すと便利かもしれません。

まとめ

今回は Microsoft Agent Framework で OpenTelemetry を使ってエージェントの入出力を可視化する方法を紹介しました。Aspire Dashboard でも Application Insights でも同様にトレースできるので、開発時は Aspire Dashboard、本番は Application Insights という使い分けができると思います。
OpenTelemetry を使うことでエージェントの動作を詳細に追跡できるようになるので、ぜひ活用してみてください。

Microsoft (有志)

Discussion