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

# Microsoft Agent Framework

> Learn how to integrate a Microsoft Agent Framework project with Splunk Agent Observability using OpenTelemetry

Splunk Agent Observability supports logging traces from [Microsoft Agent Framework](https://github.com/microsoft/agent-framework) applications using OpenTelemetry. The framework has built-in OTel instrumentation, so no extra instrumentation package is needed.

## Set up OpenTelemetry

To log Microsoft Agent Framework traces using Splunk Agent Observability, the first step is to set up OpenTelemetry.

<Steps>
  <Step title="Installation">
    Add the OpenTelemetry packages to your project:

    <CodeGroup>
      ```bash Terminal theme={null}
      pip install opentelemetry-api opentelemetry-sdk \
                  opentelemetry-exporter-otlp
      ```
    </CodeGroup>

    The `opentelemetry-api` and `opentelemetry-sdk` packages provide the core OpenTelemetry functionality. The `opentelemetry-exporter-otlp` package enables sending traces to Splunk Agent Observability's OTLP endpoint.
  </Step>

  <Step title="Create environment variables for your Splunk Agent Observability settings">
    Set environment variables for your Splunk Agent Observability settings, for example in a `.env` file.
    These environment variables are consumed by the `SplunkAOSpanProcessor`to authenticate
    and route traces to the correct Splunk Agent Observability Project and Agent Stream:

    <CodeGroup>
      ```ini .env theme={null}
      # Provide your Splunk Agent Observability
      # API key and URL if you are using an
      # on-premises, standalone, or custom deployment
      # SPLUNK_AO_API_KEY="your-splunk-ao-api-key"
      # SPLUNK_AO_CONSOLE_URL="your-splunk-ao-url"

      # Your Splunk Agent Observability project name
      SPLUNK_AO_PROJECT="your-splunk-ao-project-name"

      # The name of the Agent Stream you want to use for logging
      SPLUNK_AO_AGENT_STREAM="your-splunk-ao-agent-stream"
      ```
    </CodeGroup>
  </Step>

  <Step title="Self hosted deployments: Set the OTel endpoint">
    <Note>
      Skip this step if you are using a hosted version.
    </Note>

    The OTel endpoint is different from Splunk Agent Observability's regular API endpoint and is specifically designed to receive telemetry data in the OTLP format.

    If you are using:

    * A cloud deployment, then you don't need to provide a custom OTel endpoint.
      The default endpoint `<your-splunk-ao-api-url>/otel/traces` will be used automatically.

    * A **self-hosted deployment**, replace the `<your-splunk-ao-api-url>/otel/traces` endpoint with your deployment URL. The format of this URL is based on your console URL, appending `/otel/traces`.

    The convention is to store this in the `SPLUNK_AO_CONSOLE_URL` environment variable. For example:

    <CodeGroup>
      ```python Python theme={null}
      os.environ["SPLUNK_AO_CONSOLE_URL"] = "<your-splunk-ao-url>"
      ```
    </CodeGroup>
  </Step>

  <Step title="Initialize and create the Splunk Agent Observability span processor">
    The `SplunkAOSpanProcessor` automatically configures authentication
    and metadata using your environment variables. It also:

    * Auto-builds OTLP headers using your Splunk Agent Observability credentials
    * Configures the correct OTLP trace endpoint
    * Registers a batch span processor that exports traces to Splunk Agent Observability

    <CodeGroup>
      ```python Python theme={null}
      from splunk_ao import otel  

      # SplunkAOSpanProcessor (no manual OTLP config required) loads the env vars for 
      # the Splunk Agent Observability API key, Project, and Agent Stream. Make sure to set them first. 
      splunk_ao_span_processor = otel.SplunkAOSpanProcessor(
          # Optional parameters if not set, uses env var
          # project=os.environ["SPLUNK_AO_PROJECT"], 
          # agentstream=os.environ.get("SPLUNK_AO_AGENT_STREAM"),  
      )
      ```
    </CodeGroup>
  </Step>
</Steps>

## Log a Microsoft Agent Framework agent using OpenTelemetry

Once OpenTelemetry is configured, you can use the `SplunkAOSpanProcessor` to capture traces from your agent.

<Steps>
  <Step title="Create the tracer provider with the Splunk Agent Observability span processor">
    Set up a `TracerProvider` with the `SplunkAOSpanProcessor` and register it as the global tracer provider:

    <CodeGroup>
      ```python Python theme={null}
      from splunk_ao.otel import SplunkAOSpanProcessor, add_splunk_ao_span_processor
      from opentelemetry import trace
      from opentelemetry.sdk.trace import TracerProvider

      tracer_provider = TracerProvider()
      splunk_ao_processor = SplunkAOSpanProcessor()
      add_splunk_ao_span_processor(tracer_provider, splunk_ao_processor)
      trace.set_tracer_provider(tracer_provider)
      ```
    </CodeGroup>
  </Step>

  <Step title="Enable the framework's instrumentation">
    Enable the Microsoft Agent Framework's built-in OTel instrumentation. Set `enable_sensitive_data=True` to send LLM inputs and outputs to Splunk Agent Observability. If set to `False`, only span metadata (timing, token counts, etc.) will be sent.

    <CodeGroup>
      ```python Python theme={null}
      from agent_framework.observability import enable_instrumentation

      enable_instrumentation(enable_sensitive_data=True)
      ```
    </CodeGroup>

    When you run your agent code, traces will be logged to Splunk Agent Observability.
  </Step>
</Steps>

## Full example

Here is a full example based on the Microsoft Agent Framework's tool calling sample. You can find this project in the [Splunk Agent Observability SDK examples repo](https://github.com/splunk/splunk-ao-python/tree/main/examples/agent/microsoft-agent-framework).

To run this example, create a `.env` file with the following values set, or set them as environment variables:

```ini .env theme={null}
# OpenAI environment variables
OPENAI_API_KEY=your-openai-api-key

# Splunk Agent Observability environment variables
SPLUNK_AO_PROJECT=your-splunk-ao-project
SPLUNK_AO_AGENT_STREAM=your-agent-stream
# Only required for on-premises, standalone, or custom deployments
# SPLUNK_AO_API_KEY=your-splunk-ao-api-key
```

Remember to update these to match your [Splunk Agent Observability API key](/references/faqs/find-keys#splunk-ao-api-key), project name, and Agent Stream name.

<CodeGroup>
  ```python Python theme={null}
  from random import randint
  from typing import Annotated

  from agent_framework import openai, tool
  from agent_framework.observability import enable_instrumentation
  from splunk_ao.otel import SplunkAOSpanProcessor, add_splunk_ao_span_processor
  from opentelemetry import trace
  from opentelemetry.sdk.trace import TracerProvider
  from pydantic import Field

  # Set up the OTel tracer provider with the Splunk Agent Observability span processor
  tracer_provider = TracerProvider()
  splunk_ao_processor = SplunkAOSpanProcessor()
  add_splunk_ao_span_processor(tracer_provider, splunk_ao_processor)
  trace.set_tracer_provider(tracer_provider)

  # Enable the Microsoft Agent Framework's built-in OTel instrumentation.
  # Set enable_sensitive_data=True to send LLM inputs and outputs to Splunk Agent Observability.
  # If set to False, only span metadata (timing, token counts, etc.) will be sent.
  enable_instrumentation(enable_sensitive_data=True)


  @tool(approval_mode="never_require")
  def get_weather(
      location: Annotated[
          str, Field(description="The location to get the weather for.")
      ],
  ) -> str:
      """Get the weather for a given location."""
      conditions = ["sunny", "cloudy", "rainy", "stormy"]
      temp = randint(10, 30)
      condition = conditions[randint(0, 3)]
      return f"The weather in {location} is {condition}, {temp}C."


  client = openai.OpenAIChatClient(model_id="gpt-4.1-mini")

  agent = client.as_agent(
      name="WeatherAgent",
      instructions="You are a helpful weather agent. "
      "Use the get_weather tool to answer questions.",
      tools=[get_weather],
  )


  async def main():
      result = await agent.run("What's the weather like in Seattle?")
      print(result)


  if __name__ == "__main__":
      import asyncio

      asyncio.run(main())
  ```
</CodeGroup>
