This repository contains samples showing different Python stacks (OpenAI SDK, Anthropic SDK, LiteLLM, PydanticAI, LangChain, Microsoft Agent Framework) for building on top of multiple Microsoft Foundry models (OpenAI, Claude, etc).
All examples authenticate to Foundry using AzureDeveloperCliCredential and reference environment variables from a .env file (produced by azd provision).
Key SDKs/frameworks used:
- OpenAI Python SDK (
openai): For calling Foundry-hosted OpenAI models via the Responses API. - Anthropic Python SDK (
anthropic): For calling Foundry-hosted Claude models via the Messages API. - LiteLLM (
litellm): A unified interface that abstracts provider differences. - PydanticAI (
pydantic-ai): Agent framework with typed tool support, works with OpenAI or Anthropic providers. - LangChain (
langchain,langchain-anthropic,langchain-azure-ai): Agent framework usingChatAnthropicfor Claude via Messages API andAzureAIOpenAIApiChatModelfor OpenAI via Responses API. - Microsoft Agent Framework (
agent-framework-*): Microsoft's agent framework, supporting OpenAI and Anthropic clients.
The Microsoft Agent Framework (MAF) GitHub repo is here: https://github.com/microsoft/agent-framework The Python changelog is here: https://github.com/microsoft/agent-framework/blob/main/python/CHANGELOG.md MAF documentation: https://learn.microsoft.com/agent-framework/
- Anthropic SDK bearer-token callable support: anthropics/anthropic-sdk-python#1496 (comment)
This affects Foundry auth ergonomics for Anthropic-based samples because the SDK currently expects a sync
AccessTokenProviderinstead of a simpler bearer-token callback shape. - LangChain Azure Anthropic Messages API support: langchain-ai/langchain-azure#673
This affects whether Claude via Foundry can be handled through
langchain-azure-aiinstead of mixinglangchain-anthropicwith Foundry-specific configuration. - MAF Anthropic workflow assistant-message compatibility fix: microsoft/agent-framework#6207 This affects multi-agent workflow chaining with Anthropic, where assistant-role messages may need re-roling to user until the upstream fix is available in a released version.
This project uses uv for dependency management. Use uv commands instead of pip:
uv add <package>
uv syncRun the repo-root test script:
./manual_test.shKeep manual_test.sh up to date whenever you add a new sample or add support for another model path in an existing sample.
When debugging HTTP interactions between Azure Python SDKs (like azure-ai-evaluation) and Azure services, there are three levels of logging you can enable:
Set the Azure SDK loggers to DEBUG level to see request URLs, headers, and status codes:
import logging
logging.basicConfig(level=logging.WARNING)
logging.getLogger("azure").setLevel(logging.DEBUG)
logging.getLogger("azure.core.pipeline.policies.http_logging_policy").setLevel(logging.DEBUG)Enable http.client debug logging to see the raw HTTP wire protocol, including request and response headers:
import http.client
http.client.HTTPConnection.debuglevel = 1Note: Response bodies will typically not be visible at this level because Azure SDKs use gzip compression, and http.client logs the raw compressed bytes.
To see actual response bodies, monkey-patch the Azure SDK's HttpLoggingPolicy.on_response method. This works because response.http_response.body() returns the decompressed content:
from azure.core.pipeline.policies import HttpLoggingPolicy
_original_on_response = HttpLoggingPolicy.on_response
def _on_response_with_body(self, request, response):
_original_on_response(self, request, response)
try:
body = response.http_response.body()
if body:
_logger = logging.getLogger("azure.core.pipeline.policies.http_logging_policy")
_logger.debug("Response body: %s", body[:4096].decode("utf-8", errors="replace"))
except Exception:
pass
HttpLoggingPolicy.on_response = _on_response_with_body