diff --git a/python/samples/02-agents/observability/advanced_manual_setup_console_output.py b/python/samples/02-agents/observability/advanced_manual_setup_console_output.py index f326733b5a..3f16a47455 100644 --- a/python/samples/02-agents/observability/advanced_manual_setup_console_output.py +++ b/python/samples/02-agents/observability/advanced_manual_setup_console_output.py @@ -8,11 +8,12 @@ from typing import Annotated from agent_framework import Message, tool from agent_framework.foundry import FoundryChatClient from agent_framework.observability import enable_instrumentation +from azure.identity import AzureCliCredential from dotenv import load_dotenv from opentelemetry._logs import set_logger_provider from opentelemetry.metrics import set_meter_provider from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler -from opentelemetry.sdk._logs.export import BatchLogRecordProcessor, ConsoleLogExporter +from opentelemetry.sdk._logs.export import BatchLogRecordProcessor, ConsoleLogRecordExporter from opentelemetry.sdk.metrics import MeterProvider from opentelemetry.sdk.metrics.export import ConsoleMetricExporter, PeriodicExportingMetricReader from opentelemetry.sdk.resources import Resource @@ -37,7 +38,7 @@ def setup_logging(): # Create and set a global logger provider for the application. logger_provider = LoggerProvider(resource=resource) # Log processors are initialized with an exporter which is responsible - logger_provider.add_log_record_processor(BatchLogRecordProcessor(ConsoleLogExporter())) + logger_provider.add_log_record_processor(BatchLogRecordProcessor(ConsoleLogRecordExporter())) # Sets the global default logger provider set_logger_provider(logger_provider) # Create a logging handler to write logging records, in OTLP format, to the exporter. @@ -115,11 +116,15 @@ async def run_chat_client() -> None: 2 spans with gen_ai.operation.name=execute_tool """ - client = FoundryChatClient() + client = FoundryChatClient(credential=AzureCliCredential()) message = "What's the weather in Amsterdam and in Paris?" print(f"User: {message}") print("Assistant: ", end="") - async for chunk in client.get_response([Message(role="user", text=message)], tools=get_weather, stream=True): + async for chunk in client.get_response( + [Message(role="user", text=message)], + stream=True, + options={"tools": [get_weather]}, + ): if chunk.text: print(chunk.text, end="") print("") diff --git a/python/samples/02-agents/observability/advanced_zero_code.py b/python/samples/02-agents/observability/advanced_zero_code.py index 45696baa7b..8f356f4d2e 100644 --- a/python/samples/02-agents/observability/advanced_zero_code.py +++ b/python/samples/02-agents/observability/advanced_zero_code.py @@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Annotated from agent_framework import Message, 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 opentelemetry.trace import SpanKind from opentelemetry.trace.span import format_trace_id @@ -90,12 +91,19 @@ async def run_chat_client(client: "SupportsChatGetResponse", stream: bool = Fals print(f"User: {message}") if stream: print("Assistant: ", end="") - async for chunk in client.get_response([Message(role="user", text=message)], tools=get_weather, stream=True): + async for chunk in client.get_response( + [Message(role="user", text=message)], + stream=True, + options={"tools": [get_weather]}, + ): if chunk.text: print(chunk.text, end="") print("") else: - response = await client.get_response([Message(role="user", text=message)], tools=get_weather) + response = await client.get_response( + [Message(role="user", text=message)], + options={"tools": [get_weather]}, + ) print(f"Assistant: {response}") @@ -103,7 +111,7 @@ async def main() -> None: with get_tracer().start_as_current_span("Zero Code", kind=SpanKind.CLIENT) as current_span: print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}") - client = FoundryChatClient() + client = FoundryChatClient(credential=AzureCliCredential()) await run_chat_client(client, stream=True) await run_chat_client(client, stream=False) diff --git a/python/samples/02-agents/observability/agent_observability.py b/python/samples/02-agents/observability/agent_observability.py index 695ff9a43f..5517b32933 100644 --- a/python/samples/02-agents/observability/agent_observability.py +++ b/python/samples/02-agents/observability/agent_observability.py @@ -7,6 +7,7 @@ from typing import Annotated from agent_framework import Agent, tool from agent_framework.foundry import FoundryChatClient from agent_framework.observability import configure_otel_providers, get_tracer +from azure.identity import AzureCliCredential from dotenv import load_dotenv from opentelemetry.trace import SpanKind from opentelemetry.trace.span import format_trace_id @@ -18,6 +19,12 @@ load_dotenv() """ This sample shows how you can observe an agent in Agent Framework by using the same observability setup function. + +Pre-requisites: +- A Foundry project +- An observability backend to receive traces and metrics (for example, a local or remote + OpenTelemetry Collector, another OTLP-compatible backend, or console exporters enabled + via environment variables). """ @@ -47,7 +54,7 @@ async def main(): print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}") agent = Agent( - client=FoundryChatClient(), + client=FoundryChatClient(credential=AzureCliCredential()), tools=get_weather, name="WeatherAgent", instructions="You are a weather assistant.", diff --git a/python/samples/02-agents/observability/configure_otel_providers_with_env_var.py b/python/samples/02-agents/observability/configure_otel_providers_with_env_var.py index 1400c8d839..b9e56df8ff 100644 --- a/python/samples/02-agents/observability/configure_otel_providers_with_env_var.py +++ b/python/samples/02-agents/observability/configure_otel_providers_with_env_var.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Annotated, Literal from agent_framework import Message, tool from agent_framework.foundry import FoundryChatClient from agent_framework.observability import configure_otel_providers, get_tracer +from azure.identity import AzureCliCredential from dotenv import load_dotenv from opentelemetry import trace from opentelemetry.trace.span import format_trace_id @@ -24,8 +25,9 @@ This sample shows how you can configure observability of an application via the When you run this sample with an OTLP endpoint or an Application Insights connection string, you should see traces, logs, and metrics in the configured backend. -If no OTLP endpoint or Application Insights connection string is configured, the sample will -output traces, logs, and metrics to the console. +Pre-requisites: +- A Foundry project +- A local OpenTelemetry Collector instance to receive the traces and metrics. """ # Load environment variables from .env file @@ -78,13 +80,18 @@ async def run_chat_client(client: "SupportsChatGetResponse", stream: bool = Fals if stream: print("Assistant: ", end="") async for chunk in client.get_response( - [Message(role="user", text=message)], tools=get_weather, stream=True + [Message(role="user", text=message)], + stream=True, + options={"tools": [get_weather]}, ): if chunk.text: print(chunk.text, end="") print("") else: - response = await client.get_response([Message(role="user", text=message)], tools=get_weather) + response = await client.get_response( + [Message(role="user", text=message)], + options={"tools": [get_weather]}, + ) print(f"Assistant: {response}") @@ -101,7 +108,7 @@ async def run_tool() -> None: with get_tracer().start_as_current_span("Scenario: AI Function", kind=trace.SpanKind.CLIENT): print("Running scenario: AI Function") weather = await get_weather.invoke(location="Amsterdam") - print(f"Weather in Amsterdam:\n{weather}") + print(f"Weather in Amsterdam:\n{weather[-1]}") async def main(scenario: Literal["client", "client_stream", "tool", "all"] = "all"): @@ -114,7 +121,7 @@ async def main(scenario: Literal["client", "client_stream", "tool", "all"] = "al with get_tracer().start_as_current_span("Sample Scenarios", kind=trace.SpanKind.CLIENT) as current_span: print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}") - client = FoundryChatClient() + client = FoundryChatClient(credential=AzureCliCredential()) # Scenarios where telemetry is collected in the SDK, from the most basic to the most complex. if scenario == "tool" or scenario == "all": diff --git a/python/samples/02-agents/observability/configure_otel_providers_with_parameters.py b/python/samples/02-agents/observability/configure_otel_providers_with_parameters.py index 6bf7a2fcd6..8fd6d76cd0 100644 --- a/python/samples/02-agents/observability/configure_otel_providers_with_parameters.py +++ b/python/samples/02-agents/observability/configure_otel_providers_with_parameters.py @@ -10,6 +10,7 @@ from typing import TYPE_CHECKING, Annotated, Literal from agent_framework import Message, tool from agent_framework.foundry import FoundryChatClient from agent_framework.observability import configure_otel_providers, get_tracer +from azure.identity import AzureCliCredential from dotenv import load_dotenv from opentelemetry import trace from opentelemetry.trace.span import format_trace_id @@ -27,6 +28,10 @@ and allows you to add multiple exporters programmatically. For standard OTLP setup, it's recommended to use environment variables (see configure_otel_providers_with_env_var.py). Use this approach when you need custom exporter configuration beyond what environment variables provide. + +Pre-requisites: +- A Foundry project +- A local OpenTelemetry Collector instance to receive the traces and metrics. """ # Load environment variables from .env file @@ -79,13 +84,18 @@ async def run_chat_client(client: "SupportsChatGetResponse", stream: bool = Fals if stream: print("Assistant: ", end="") async for chunk in client.get_response( - [Message(role="user", text=message)], stream=True, tools=get_weather + [Message(role="user", text=message)], + stream=True, + options={"tools": [get_weather]}, ): if chunk.text: print(chunk.text, end="") print("") else: - response = await client.get_response([Message(role="user", text=message)], tools=get_weather) + response = await client.get_response( + [Message(role="user", text=message)], + options={"tools": [get_weather]}, + ) print(f"Assistant: {response}") @@ -102,7 +112,7 @@ async def run_tool() -> None: with get_tracer().start_as_current_span("Scenario: AI Function", kind=trace.SpanKind.CLIENT): print("Running scenario: AI Function") weather = await get_weather.invoke(location="Amsterdam") - print(f"Weather in Amsterdam:\n{weather}") + print(f"Weather in Amsterdam:\n{weather[-1]}") async def main(scenario: Literal["client", "client_stream", "tool", "all"] = "all"): @@ -153,7 +163,7 @@ async def main(scenario: Literal["client", "client_stream", "tool", "all"] = "al with get_tracer().start_as_current_span("Sample Scenarios", kind=trace.SpanKind.CLIENT) as current_span: print(f"Trace ID: {format_trace_id(current_span.get_span_context().trace_id)}") - client = FoundryChatClient() + client = FoundryChatClient(credential=AzureCliCredential()) # Scenarios where telemetry is collected in the SDK, from the most basic to the most complex. if scenario == "tool" or scenario == "all":