Python: improve .env handling and observability samples (#4032)

* Python: improve .env precedence and observability samples

- Switch load_settings to explicit precedence: overrides -> explicit .env -> environment -> defaults\n- Raise when env_file_path is provided but missing\n- Update settings docs and tests for new behavior\n- Refresh observability samples and README guidance for env loading options\n\nCloses #3864\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fixed some imports

* Fix load_settings CI regressions

Allow explicit env_file_path values that exist but are not regular files (for example /dev/null) by checking path existence before dotenv parsing, and restore a dict accumulator with typed return cast to satisfy mypy.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Avoid implicit dotenv in observability

Only load dotenv in observability helpers when env_file_path is explicitly provided, and remove test os.devnull workarounds that are no longer necessary.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Eduard van Valkenburg
2026-02-18 12:18:52 +01:00
committed by GitHub
Unverified
parent f900febb6f
commit 534e5f5bf7
41 changed files with 250 additions and 221 deletions
@@ -4,7 +4,7 @@ import asyncio
from random import randint
from typing import TYPE_CHECKING, Annotated
from agent_framework import tool
from agent_framework import Message, tool
from agent_framework.observability import get_tracer
from agent_framework.openai import OpenAIResponsesClient
from opentelemetry.trace import SpanKind
@@ -20,13 +20,14 @@ This sample shows how you can configure observability of an application with zer
It relies on the OpenTelemetry auto-instrumentation capabilities, and the observability setup
is done via environment variables.
Follow the install guidance from https://opentelemetry.io/docs/zero-code/python/ to install the OpenTelemetry CLI tool.
Follow the install guidance from https://opentelemetry.io/docs/zero-code/python/ to install the OpenTelemetry CLI tool,
when using `uv` there are some additional steps, so follow the instructions carefully.
And setup a local OpenTelemetry Collector instance to receive the traces and metrics (and update the endpoint below).
Then you can run:
```bash
opentelemetry-enable_instrumentation \
opentelemetry-instrument \
--traces_exporter otlp \
--metrics_exporter otlp \
--service_name agent_framework \
@@ -40,7 +41,9 @@ You can also set the environment variables instead of passing them as CLI argume
"""
# NOTE: approval_mode="never_require" is for sample brevity. Use "always_require" in production; see samples/02-agents/tools/function_tool_with_approval.py and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
# NOTE: approval_mode="never_require" is for sample brevity.
# Use "always_require" in production; see samples/02-agents/tools/function_tool_with_approval.py
# and samples/02-agents/tools/function_tool_with_approval_and_sessions.py.
@tool(approval_mode="never_require")
async def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
@@ -81,12 +84,12 @@ 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, tools=get_weather, stream=True):
if str(chunk):
print(str(chunk), end="")
async for chunk in client.get_response([Message(role="user", text=message)], tools=get_weather, stream=True):
if chunk.text:
print(chunk.text, end="")
print("")
else:
response = await client.get_response(message, tools=get_weather)
response = await client.get_response([Message(role="user", text=message)], tools=get_weather)
print(f"Assistant: {response}")