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
13 changes: 13 additions & 0 deletions python/packages/foundry/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@ This package supports `azure-ai-projects>=2.2.0,<2.7.0`. Projects 2.5 and later
`openai>=3.0.0`, so `agent-framework-foundry` requires `agent-framework-openai>=1.14.2`,
which supports both OpenAI 2.x and 3.x.

## Tracing an existing Foundry agent

Install Azure Monitor to connect client and service traces:

```shell
pip install --upgrade agent-framework-foundry "azure-monitor-opentelemetry>=1.8.10,<2"
```

With Application Insights connected to your project, call
`await agent.configure_azure_monitor()` before invoking a `FoundryAgent`.
See [the tracing sample](../../samples/02-agents/observability/foundry_agent_tracing.py)
for streaming and non-streaming examples.

## Evaluations

`FoundryEvals` implements the provider-neutral `Evaluator` protocol with
Expand Down
6 changes: 4 additions & 2 deletions python/packages/foundry/agent_framework_foundry/_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -856,14 +856,16 @@ async def configure_azure_monitor(

This method configures Azure Monitor for telemetry collection using the
connection string from the Foundry project client (accessed via the internal client).
Use azure-monitor-opentelemetry>=1.8.10,<2 for HTTPX/HTTPX2
auto-instrumentation that connects client and service traces.

Args:
enable_sensitive_data: Enable sensitive data logging (prompts, responses).
Should only be enabled in development/test environments. Default is False.
**kwargs: Additional arguments passed to configure_azure_monitor().

Raises:
ImportError: If azure-monitor-opentelemetry-exporter is not installed.
ImportError: If azure-monitor-opentelemetry is not installed.
"""
from agent_framework.observability import (
OBSERVABILITY_SETTINGS,
Expand Down Expand Up @@ -900,7 +902,7 @@ async def configure_azure_monitor(
except ImportError as exc:
raise ImportError(
"azure-monitor-opentelemetry is required for Azure Monitor integration. "
"Install it with: pip install azure-monitor-opentelemetry"
'Install it with: pip install "azure-monitor-opentelemetry>=1.8.10,<2"'
) from exc

if "resource" not in kwargs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ async def configure_azure_monitor(

This method configures Azure Monitor for telemetry collection using the
connection string from the Foundry project client.
Use azure-monitor-opentelemetry>=1.8.10,<2 for HTTPX/HTTPX2
auto-instrumentation that connects client and service traces.

Args:
enable_sensitive_data: Enable sensitive data logging (prompts, responses).
Expand All @@ -319,7 +321,7 @@ async def configure_azure_monitor(
- resource (Resource): Custom OpenTelemetry resource

Raises:
ImportError: If azure-monitor-opentelemetry-exporter is not installed.
ImportError: If azure-monitor-opentelemetry is not installed.
"""
from agent_framework.observability import (
OBSERVABILITY_SETTINGS,
Expand Down Expand Up @@ -352,7 +354,7 @@ async def configure_azure_monitor(
except ImportError as exc:
raise ImportError(
"azure-monitor-opentelemetry is required for Azure Monitor integration. "
"Install it with: pip install azure-monitor-opentelemetry"
'Install it with: pip install "azure-monitor-opentelemetry>=1.8.10,<2"'
) from exc

if "resource" not in kwargs:
Expand Down
2 changes: 1 addition & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ dev = [
"griffe==2.3.0",
]
test = [
"azure-monitor-opentelemetry",
"azure-monitor-opentelemetry>=1.8.10,<2",
"mcp[ws]",
# Optional SDK used by the agent-hooks tests and isolated source checks.
"agent-hooks-sdk>=0.1.0a4,<0.2",
Expand Down
26 changes: 25 additions & 1 deletion python/samples/02-agents/observability/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ configure_azure_monitor(
enable_sensitive_telemetry()
```

For Microsoft Foundry projects, use `client.configure_azure_monitor()` which retrieves the connection string from the project and configures everything:
For model calls through `FoundryChatClient`, use `client.configure_azure_monitor()`
to retrieve the connection string and configure Azure Monitor:

```python
from agent_framework.foundry import FoundryChatClient
Expand All @@ -131,6 +132,29 @@ client = FoundryChatClient(
await client.configure_azure_monitor(enable_sensitive_data=True)
```

For calls to an **existing prompt or hosted agent**, use
[`foundry_agent_tracing.py`](foundry_agent_tracing.py) and
`await agent.configure_azure_monitor()`.

Install Azure Monitor 1.8.10 or later to connect client and service traces:

```shell
pip install --upgrade "azure-monitor-opentelemetry>=1.8.10,<2"
```

Connect Application Insights to your project and set `FOUNDRY_PROJECT_ENDPOINT`
and `FOUNDRY_AGENT_NAME`. `FOUNDRY_AGENT_VERSION` is required for PromptAgents
and optional for HostedAgents. Run from `python/` using the workspace packages:

```powershell
uv run --group test python samples\02-agents\observability\foundry_agent_tracing.py
uv run --group test python samples\02-agents\observability\foundry_agent_tracing.py --stream
```

View the connected trace under **Build > Agents > your agent > Traces** in
Foundry. Select the agent version and a time range covering the run, then open
the printed trace ID.

Or with [Langfuse](https://langfuse.com/integrations/frameworks/microsoft-agent-framework):

```python
Expand Down
98 changes: 98 additions & 0 deletions python/samples/02-agents/observability/foundry_agent_tracing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "agent-framework-foundry",
# "azure-monitor-opentelemetry>=1.8.10,<2",
# ]
# ///
# Run from python/ with the workspace environment:
# uv run --group test python samples/02-agents/observability/foundry_agent_tracing.py

# Copyright (c) Microsoft. All rights reserved.

from __future__ import annotations

import argparse
import asyncio
import os

from agent_framework.foundry import FoundryAgent
from agent_framework.observability import get_tracer
from azure.identity.aio import AzureCliCredential
from dotenv import load_dotenv
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider

"""
Trace calls to an existing Foundry agent, including the client and service spans.

Azure Monitor 1.8.10 or later instruments HTTPX and HTTPX2, which the OpenAI SDK
uses to send requests. The resulting traceparent header connects client spans
to Foundry's service spans. Older Azure Monitor versions can export the client
spans to Application Insights while leaving them in a separate trace.

The helper configures Azure Monitor using the project's connected Application
Insights resource. No project ARM ID or custom span attributes are needed.
Add --stream for streaming output. Message-content recording remains disabled.

Environment variables:
FOUNDRY_PROJECT_ENDPOINT -- Foundry project endpoint.
FOUNDRY_AGENT_NAME -- Existing prompt or hosted agent name.
FOUNDRY_AGENT_VERSION -- Required for PromptAgents; optional for HostedAgents.

After running, open Build > Agents > your agent > Traces in Foundry. Select the
agent version and a time range covering the run, then open the printed trace ID.
The waterfall should contain this application's parent span, client invoke_agent
and chat spans, the HTTP request, and the service spans in one connected tree.
The sample does not create or delete the agent, so it remains available for inspection.
"""

load_dotenv()


async def main() -> None:
parser = argparse.ArgumentParser(description="Trace client and service calls to an existing Foundry agent.")
parser.add_argument("--stream", action="store_true", help="Stream the agent response.")
args = parser.parse_args()

# 1. Connect to an existing agent without changing its definition.
async with (
AzureCliCredential() as credential,
FoundryAgent(
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
agent_name=os.environ["FOUNDRY_AGENT_NAME"],
agent_version=os.getenv("FOUNDRY_AGENT_VERSION"),
credential=credential,
) as agent,
):
# 2. Configure export and HTTP trace-context propagation before invoking the agent.
await agent.configure_azure_monitor(enable_live_metrics=False)

# 3. Group the client operation beneath an application span.
with get_tracer().start_as_current_span("foundry-agent-tracing") as span:
print(f"Trace ID: {span.get_span_context().trace_id:032x}")
if args.stream:
result_stream = agent.run("Say hello in one sentence.", stream=True)
async for update in result_stream:
if update.text:
print(update.text, end="", flush=True)
print()
response = await result_stream.get_final_response()
else:
response = await agent.run("Say hello in one sentence.")
print(response.text)
print(f"Agent response ID: {response.response_id}")

# 4. Flush before exit; exporting does not by itself prove Foundry portal discovery.
provider = trace.get_tracer_provider()
if isinstance(provider, TracerProvider) and not provider.force_flush():
raise TimeoutError("Trace export did not finish before the flush timeout.")


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

# Example output:
# Trace ID: <trace ID to search for in Foundry>
# Hello! How can I help you today?
# Agent response ID: <service response ID>
6 changes: 5 additions & 1 deletion python/samples/02-agents/observability/foundry_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# requires-python = ">=3.10"
# dependencies = [
# "agent-framework-foundry",
# "azure-monitor-opentelemetry",
# "azure-monitor-opentelemetry>=1.8.10,<2",
# ]
# ///
# Run with any PEP 723 compatible runner, e.g.:
Expand All @@ -29,6 +29,10 @@
This sample shows how to setup telemetry in Microsoft Foundry for a custom agent
using ``FoundryChatClient.configure_azure_monitor()``.

For an existing Foundry prompt or hosted agent, see ``foundry_agent_tracing.py``
instead. Azure Monitor 1.8.10 or later instruments the HTTP transport so client
and service spans can share a trace.

First ensure you have a Foundry workspace with Application Insights enabled.
And use the Operate tab to Register an Agent.
Set the OpenTelemetry agent ID to the value used below in the Agent creation: ``weather-agent``
Expand Down
1 change: 1 addition & 0 deletions python/samples/02-agents/providers/foundry/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This folder contains Microsoft Foundry and Foundry Local samples for Agent Frame
| [`foundry_agent_custom_client.py`](foundry_agent_custom_client.py) | Foundry Agent custom client configuration |
| [`foundry_agent_hosted.py`](foundry_agent_hosted.py) | Foundry Agent for hosted agents |
| [`foundry_agent_with_function_tools.py`](foundry_agent_with_function_tools.py) | Foundry Agent with local function tools |
| [`foundry_agent_tracing.py`](../../observability/foundry_agent_tracing.py) | Connected client and service traces for an existing Foundry agent, with optional streaming |

## FoundryChatClient Samples

Expand Down
2 changes: 1 addition & 1 deletion python/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading