Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@

import httpx
from agent_framework import (
AggregatingSkillsSource,
Agent,
AgentModeProvider,
AggregatingSkillsSource,
DeduplicatingSkillsSource,
FileAccessProvider,
FileSkillsSource,
Expand All @@ -84,7 +84,6 @@
# subprocess script runner used to execute file-based skill scripts.
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from console import build_observers_with_planning, run_agent_async # noqa: E402

from subprocess_script_runner import subprocess_script_runner # noqa: E402

_SAMPLE_DIR = Path(__file__).resolve().parent
Expand Down
11 changes: 11 additions & 0 deletions python/samples/02-agents/observability/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ configure_otel_providers(exporters=exporters)

Many third-party OTel packages ship their own setup helpers (for example, Azure Monitor's `configure_azure_monitor()`). You can use those directly — Agent Framework instrumentation is on by default, so no extra wiring is needed. To also capture sensitive data, call `enable_sensitive_telemetry()` from `agent_framework.observability`.

The [Microsoft OpenTelemetry Distro](https://pypi.org/project/microsoft-opentelemetry/) bundles this pattern into a single call. Install it with `pip install microsoft-opentelemetry`, then call `use_microsoft_opentelemetry()`, which wires up the OpenTelemetry providers/exporters (optionally including Azure Monitor) and enables Agent Framework instrumentation:

```python
from microsoft.opentelemetry import use_microsoft_opentelemetry

# Sets up OpenTelemetry providers/exporters and enables Agent Framework instrumentation.
# Pass enable_azure_monitor=True to also configure the Azure Monitor exporter.
use_microsoft_opentelemetry(enable_azure_monitor=True)
```

```python
from azure.monitor.opentelemetry import configure_azure_monitor
from agent_framework.observability import create_resource, enable_sensitive_telemetry
Expand Down Expand Up @@ -334,6 +344,7 @@ This folder contains different samples demonstrating how to use telemetry in var
| [configure_otel_providers_with_parameters.py](./configure_otel_providers_with_parameters.py) | Create custom exporters with specific configuration and pass them to `configure_otel_providers()`. |
| [agent_observability.py](./agent_observability.py) | Telemetry collection for an agentic application with tool calls. |
| [foundry_tracing.py](./foundry_tracing.py) | Azure Monitor integration with Microsoft Foundry. |
| [microsoft_opentelemetry_distro.py](./microsoft_opentelemetry_distro.py) | One-call setup with the Microsoft OpenTelemetry Distro (`use_microsoft_opentelemetry()`), optionally enabling Azure Monitor. |
| [workflow_observability.py](./workflow_observability.py) | Telemetry collection for a workflow with multiple executors and message passing. |
| [advanced_manual_setup_console_output.py](./advanced_manual_setup_console_output.py) | Advanced: manual setup of exporters and providers with console output — useful for understanding how observability works under the hood. |
| [advanced_zero_code.py](./advanced_zero_code.py) | Advanced: zero-code provider/exporter setup using the `opentelemetry-instrument` CLI wrapper. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "agent-framework-foundry",
# "microsoft-opentelemetry",
Comment thread
TaoChenOSU marked this conversation as resolved.
# ]
# ///
# Run with any PEP 723 compatible runner, e.g.:
# uv run python/samples/02-agents/observability/microsoft_opentelemetry_distro.py

# Copyright (c) Microsoft. All rights reserved.
Comment thread
TaoChenOSU marked this conversation as resolved.

import asyncio
from random import randint
from typing import Annotated

from agent_framework import Agent, tool
from agent_framework.foundry import FoundryChatClient
from agent_framework.observability import get_tracer
from azure.identity import AzureCliCredential
from dotenv import load_dotenv
from microsoft.opentelemetry import use_microsoft_opentelemetry
Comment thread
TaoChenOSU marked this conversation as resolved.
from opentelemetry.trace import SpanKind
from opentelemetry.trace.span import format_trace_id
from pydantic import Field

# Load environment variables from .env file
load_dotenv()


@tool(approval_mode="never_require")
async def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
"""Get the weather for a given location."""
await asyncio.sleep(randint(0, 10) / 10.0) # Simulate a network call
conditions = ["sunny", "cloudy", "rainy", "stormy"]
return f"The weather in {location} is {conditions[randint(0, 3)]} with a high of {randint(10, 30)}°C."


async def main():
# Set up Azure monitor exporters for telemetry
# This will automatically enable instrumentation for Agent Framework
# Install the Microsoft OpenTelemetry Distro package to enable this functionality:
# pip install microsoft-opentelemetry
# Requires the following environment variables to be set:
# OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
# APPLICATIONINSIGHTS_CONNECTION_STRING=InstrumentationKey...
use_microsoft_opentelemetry(enable_azure_monitor=True)
Comment thread
TaoChenOSU marked this conversation as resolved.
Comment thread
TaoChenOSU marked this conversation as resolved.

questions = [
"What's the weather in Amsterdam?",
"and in Paris, and which is better?",
"Why is the sky blue?",
]

with get_tracer().start_as_current_span(
"Scenario: Agent Chat", kind=SpanKind.CLIENT
) as current_span:
print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}")

agent = Agent(
client=FoundryChatClient(credential=AzureCliCredential()),
tools=get_weather,
name="WeatherAgent",
instructions="You are a weather assistant.",
id="weather-agent",
)
session = agent.create_session()
for question in questions:
print(f"\nUser: {question}")
print(f"{agent.name}: ", end="")
async for update in agent.run(question, session=session, stream=True):
if update.text:
print(update.text, end="")


if __name__ == "__main__":
asyncio.run(main())
Loading