> ## Documentation Index
> Fetch the complete documentation index at: /docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Microsoft Agent Framework for C#

> Trace Microsoft Agent Framework agents in C# with OpenTelemetry GenAI and send spans to Arize AX.

[Microsoft Agent Framework](https://learn.microsoft.com/en-us/agent-framework/overview/?pivots=programming-language-csharp) is Microsoft's open-source SDK for building AI agents. Its C# SDK emits OpenTelemetry spans using GenAI semantic conventions. Arize AX ingests these spans directly and displays agent, model, and tool activity without an OpenInference processor.

## Prerequisites

* .NET 10 SDK
* An Arize AX account ([sign up](https://arize.com/sign-up/))
* An `OPENAI_API_KEY` from the [OpenAI Platform](https://platform.openai.com/api-keys)

## Launch Arize AX

1. Sign in to your [Arize AX account](https://app.arize.com/).
2. From **Space Settings**, copy your **Space ID** and **API Key**. You will set them as `ARIZE_SPACE_ID` and `ARIZE_API_KEY` below.

## Install

Create a console project and add the Microsoft Agent Framework OpenAI connector and the OpenTelemetry Protocol exporter:

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
dotnet new console --framework net10.0 --name MicrosoftAgentFramework
cd MicrosoftAgentFramework
dotnet add package Microsoft.Agents.AI.OpenAI --version 1.24.0
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol --version 1.19.1
```

## Configure credentials

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
export ARIZE_SPACE_ID="<your-space-id>"
export ARIZE_API_KEY="<your-api-key>"
export ARIZE_PROJECT_NAME="microsoft-agent-framework-csharp-example"
export OPENAI_API_KEY="<your-openai-api-key>"
```

## Setup tracing

The example configures an OTLP gRPC exporter for Arize AX, adds the project name as a resource attribute, and instruments one agent with a `GetWeather` function tool. GPT-6.1 Sol requires the Responses API for tool calling, so the agent uses `GetResponsesClient()` ([OpenAI model documentation](https://developers.openai.com/api/docs/models/gpt-6.1-sol)).

`EnableSensitiveData = true` records prompts, responses, tool arguments, and tool results. Use it only when that data is appropriate for your Arize AX project and its retention policy. Set it to `false` to omit message content.

```csharp C# theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
#pragma warning disable OPENAI001

using System.ComponentModel;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI;
using OpenAI.Responses;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

const string sourceName = "Microsoft.AgentFramework.Sample";
var apiKey = Environment.GetEnvironmentVariable("ARIZE_API_KEY")!;
var spaceId = Environment.GetEnvironmentVariable("ARIZE_SPACE_ID")!;
var projectName = Environment.GetEnvironmentVariable("ARIZE_PROJECT_NAME")
    ?? "microsoft-agent-framework-csharp-example";
var openAiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!;

using var tracerProvider = Sdk.CreateTracerProviderBuilder()
    .SetResourceBuilder(ResourceBuilder.CreateDefault()
        .AddService("microsoft-agent-framework-csharp")
        .AddAttributes(new Dictionary<string, object>
        {
            ["openinference.project.name"] = projectName
        }))
    .AddSource(sourceName)
    .AddOtlpExporter(options =>
    {
        options.Endpoint = new Uri("https://otlp.arize.com:443");
        options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
        options.Headers = $"authorization={apiKey},"+
                          $"arize-space-id={spaceId}," +
                          "arize-interface=dotnet";
    })
    .Build();

Console.WriteLine("Arize AX tracing initialized.");

var openAiClient = new OpenAIClient(openAiKey);

var agent = openAiClient.GetResponsesClient().AsAIAgent(
        model: "gpt-6.1-sol",
        name: "weather-agent",
        instructions:
            "You are a concise weather assistant. Always call the GetWeather " +
            "tool once before answering.",
        tools: [AIFunctionFactory.Create(WeatherTools.GetWeather)])
    .AsBuilder()
    .UseOpenTelemetry(
        sourceName, telemetry => telemetry.EnableSensitiveData = true)
    .Build();
```

The agent instrumentation emits the agent invocation, chat client, and function execution spans. The tracer provider listens to the same source name passed to `UseOpenTelemetry` and exports those spans directly to Arize AX.

## Add a tool

Create `WeatherTools.cs` for the function tool used by the agent:

```csharp C# theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
using System.ComponentModel;

static class WeatherTools
{
    [Description("Returns the current weather for a city.")]
    public static string GetWeather(
        [Description("The city to check.")] string city) =>
        $"Sunny and 72°F in {city}.";
}
```

## Run Microsoft Agent Framework

Add the agent invocation to the end of `Program.cs`:

```csharp C# theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
var result = await agent.RunAsync("What is the weather in San Francisco?");
Console.WriteLine(result);
```

Run the project from the `MicrosoftAgentFramework` directory:

```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
dotnet run --project MicrosoftAgentFramework.csproj
```

### Expected output

```text wrap theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
Arize AX tracing initialized.
Sunny and 72°F in San Francisco.
```

## Verify in Arize AX

1. Open your Arize AX space and select project **`microsoft-agent-framework-csharp-example`**.
2. You should see a trace with an `invoke_agent` root span, chat spans for the model calls, and an `execute_tool` span for `GetWeather`. The model spans include provider, model, token usage, and message attributes.
3. If no traces appear, see [Troubleshooting](#troubleshooting).

Confirm spans are actually reaching your Arize AX project. Use whichever fits your workflow — the skill and CLI work for any framework; the SDK check is shown for each language.

> [tab] Arize skill (agent)
>
> Install the [Arize Skills](https://github.com/Arize-ai/arize-skills) plugin and let your coding agent check for you:
>
> ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
> npx skills add Arize-ai/arize-skills
> ```
>
> Then prompt your agent:
>
> > Use the `arize-trace` skill to export and analyze recent traces from my project. Confirm spans are arriving, and summarize any errors or latency issues.

> [tab] AX CLI
>
> Export recent spans for your project — any rows mean traces are landing:
>
> ```bash theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
> ax spans export "$ARIZE_PROJECT_NAME" --space "$ARIZE_SPACE_ID" \
>   --limit 5 --stdout | jq 'length'
> ```
>
> A non-zero count confirms spans reached Arize AX. Run `ax auth login` first if you have not authenticated. See the [`ax spans` reference](/docs/api-clients/cli/spans).

> [tab] SDK
>
> Query the project's spans and check that at least one came back.
>
> ```python Python theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
> import os
> from arize import ArizeClient
>
> client = ArizeClient(api_key=os.environ["ARIZE_API_KEY"])
> resp = client.spans.list(
>     project=os.environ["ARIZE_PROJECT_NAME"],
>     space=os.environ["ARIZE_SPACE_ID"],
>     limit=5,
> )
> count = len(resp.spans)
> print(
>     f"{count} span(s) found" if count else "No spans yet — recheck setup"
> )
> ```
>
> ```typescript TypeScript theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
> // Reads ARIZE_API_KEY from the environment.
> import { listSpans } from "@arizeai/ax-client";
>
> const { data: spans } = await listSpans({
>   project: process.env.ARIZE_PROJECT_NAME!,
>   space: process.env.ARIZE_SPACE_ID!,
>   limit: 5,
> });
> const count = spans.length;
> console.log(
>   count ? `${count} span(s) found` : "No spans yet — recheck setup",
> );
> ```
>
> ```go Go theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
> client, err := arize.NewClient(
>     arize.Config{APIKey: os.Getenv("ARIZE_API_KEY")},
> )
> if err != nil {
>     log.Fatal(err)
> }
> resp, err := client.Spans.List(ctx, spans.ListRequest{
>     Project: os.Getenv("ARIZE_PROJECT_NAME"),
>     Space:   os.Getenv("ARIZE_SPACE_ID"),
>     Limit:   5,
> })
> if err != nil {
>     log.Fatal(err)
> }
> fmt.Printf("%d span(s) found\n", len(resp.Spans))
> ```
>
> SDK span references: [Python](/docs/api-clients/python/version-8/client-resources/spans.md) · [TypeScript](/docs/api-clients/typescript/version-1/client-resources/spans.md) · [Go](/docs/api-clients/go/version-2/client-resources/spans.md).

## Troubleshooting

* **No traces in Arize AX.** Confirm `ARIZE_SPACE_ID` and `ARIZE_API_KEY` are set in the same shell that runs `dotnet run`, and confirm the exporter endpoint and headers match the example.
* **No agent spans.** The source name passed to `UseOpenTelemetry` must match the source registered with `.AddSource(sourceName)`.
* **Wrong project.** Confirm the `openinference.project.name` resource attribute is set to the value of `ARIZE_PROJECT_NAME`.
* **Prompts or tool content are missing.** Set `EnableSensitiveData = true` for the agent's OpenTelemetry configuration. This also records those values in traces, so enable it only when appropriate.
* **`401` from OpenAI.** Verify `OPENAI_API_KEY` is valid and can access `gpt-6.1-sol`. Replace the model with one available to your account if needed.
* **Package restore or build fails.** Confirm the .NET 10 SDK is installed and that the package versions in the project file match the versions shown above.

## Resources

> [card] [Microsoft Agent Framework Documentation](https://learn.microsoft.com/en-us/agent-framework/overview/?pivots=programming-language-csharp)

> [card] [Microsoft Agent Framework Observability](https://learn.microsoft.com/en-us/agent-framework/agents/observability?pivots=programming-language-csharp)

> [card] [Microsoft Agent Framework GitHub](https://github.com/microsoft/agent-framework)
