Python: [BREAKING] Python: move Azure AI embeddings to Foundry (#5056)

* renamed AzureAIINferenceEmbeddings and lazy load azure-cosmos and env var rename

* updated coverage

* fix readme
This commit is contained in:
Eduard van Valkenburg
2026-04-02 13:26:35 +02:00
committed by GitHub
Unverified
parent 47d82911c0
commit 95fd5ec658
74 changed files with 403 additions and 978 deletions
+12 -3
View File
@@ -1,6 +1,15 @@
# Azure AI
# Microsoft Foundry
FOUNDRY_PROJECT_ENDPOINT=""
# Model used for FoundryChatClient
FOUNDRY_MODEL=""
# Foundry Agents (prompt or hosted agents)
FOUNDRY_AGENT_NAME=""
FOUNDRY_AGENT_VERSION=""
# Microsoft Foundry Models endpoint, used by embeddings
FOUNDRY_MODELS_ENDPOINT=""
FOUNDRY_MODELS_API_KEY=""
FOUNDRY_EMBEDDING_MODEL=""
FOUNDRY_IMAGE_EMBEDDING_MODEL=""
# Bing connection for web search (optional, used by samples with web search)
BING_CONNECTION_ID=""
# Azure AI Search (optional, used by AzureAISearchContextProvider samples)
@@ -13,12 +22,12 @@ AZURE_SEARCH_KNOWLEDGE_BASE_NAME=""
# (different from AZURE_AI_PROJECT_ENDPOINT - Knowledge Base needs OpenAI endpoint for model calls)
# OpenAI
OPENAI_API_KEY=""
OPENAI_CHAT_COMPLETION_MODEL=""
OPENAI_CHAT_MODEL=""
OPENAI_RESPONSES_MODEL=""
# Azure OpenAI
AZURE_OPENAI_ENDPOINT=""
AZURE_OPENAI_CHAT_COMPLETION_MODEL=""
AZURE_OPENAI_CHAT_MODEL=""
AZURE_OPENAI_RESPONSES_MODEL=""
# Mem0
MEM0_API_KEY=""
# Copilot Studio
+3 -3
View File
@@ -15,7 +15,7 @@ python/
├── pyproject.toml # Root package (agent-framework)
├── packages/
│ ├── core/ # agent-framework-core (main package)
│ ├── azure-ai/ # agent-framework-azure-ai
│ ├── foundry/ # agent-framework-foundry
│ ├── anthropic/ # agent-framework-anthropic
│ └── ... # Other connector packages
```
@@ -76,9 +76,9 @@ uv run poe add-dependency-and-validate-bounds --package core --dependency "<depe
Provider folders in core use `__getattr__` to lazy load from connector packages:
```python
# In agent_framework/azure/__init__.py
# In agent_framework/foundry/__init__.py
_IMPORTS: dict[str, tuple[str, str]] = {
"AzureAIAgentClient": ("agent_framework_azure_ai", "agent-framework-azure-ai"),
"FoundryChatClient": ("agent_framework_foundry", "agent-framework-foundry"),
}
def __getattr__(name: str) -> Any:
+1 -1
View File
@@ -124,7 +124,7 @@ The merge CI workflow (`python-merge-tests.yml`) splits integration tests into p
- **Azure OpenAI integration** — runs when `packages/core/agent_framework/azure/` or core changes
- **Misc integration** — Anthropic, Ollama, MCP tests; runs when their packages or core change
- **Functions integration** — Azure Functions + Durable Task; runs when their packages or core change
- **Azure AI integration** — runs when `packages/azure-ai/` or core changes
- **Foundry integration** — runs when `packages/foundry/` or core changes
Core infrastructure changes (e.g., `_agents.py`, `_types.py`) trigger all integration test jobs. Scheduled and manual runs always execute all jobs.
+4 -3
View File
@@ -40,7 +40,7 @@ python/
│ ├── core/ # agent-framework-core (main package)
│ │ ├── agent_framework/ # Public API exports
│ │ └── tests/
│ ├── azure-ai/ # agent-framework-azure-ai
│ ├── foundry/ # agent-framework-foundry
│ ├── anthropic/ # agent-framework-anthropic
│ ├── ollama/ # agent-framework-ollama
│ └── ... # Other provider packages
@@ -52,7 +52,7 @@ python/
### Package Relationships
- `agent-framework-core` contains core abstractions and OpenAI/Azure OpenAI built-in
- Provider packages (`azure-ai`, `anthropic`, etc.) extend core with specific integrations
- Provider packages (`foundry`, `anthropic`, etc.) extend core with specific integrations
- Core uses lazy loading via `__getattr__` in provider folders (e.g., `agent_framework/azure/`)
## Package Documentation
@@ -68,8 +68,9 @@ python/
- [ollama](packages/ollama/AGENTS.md) - Local Ollama inference
### Azure Integrations
- [azure-ai](packages/azure-ai/AGENTS.md) - Azure AI Foundry agents
- [foundry](packages/foundry/README.md) - Microsoft Foundry chat, agent, memory, and embedding integrations
- [azure-ai-search](packages/azure-ai-search/AGENTS.md) - Azure AI Search RAG
- [azure-cosmos](packages/azure-cosmos/AGENTS.md) - Azure Cosmos DB-backed history provider
- [azurefunctions](packages/azurefunctions/AGENTS.md) - Azure Functions hosting
### Protocols & UI
+9 -8
View File
@@ -325,14 +325,15 @@ python/
│ │ ├── mem0/ # Lazy loads from agent-framework-mem0
│ │ └── redis/ # Lazy loads from agent-framework-redis
│ │
│ ├── azure-ai/ # agent-framework-azure-ai
│ ├── foundry/ # agent-framework-foundry
│ │ ├── pyproject.toml
│ │ ├── tests/
│ │ └── agent_framework_azure_ai/
│ │ └── agent_framework_foundry/
│ │ ├── __init__.py # Public exports
│ │ ├── _chat_client.py # AzureAIClient implementation
│ │ ├── _client.py # AzureAIAgentClient implementation
│ │ ├── _shared.py # AzureAISettings and shared utilities
│ │ ├── _chat_client.py # FoundryChatClient implementation
│ │ ├── _agent.py # FoundryAgent implementation
│ │ ├── _embedding_client.py # FoundryEmbeddingClient implementation
│ │ ├── _memory_provider.py # Foundry memory implementation
│ │ └── py.typed # PEP 561 marker
│ ├── anthropic/ # agent-framework-anthropic
│ ├── bedrock/ # agent-framework-bedrock
@@ -345,9 +346,9 @@ python/
Provider folders in the core package use `__getattr__` to lazy load classes from their respective connector packages. This allows users to import from a consistent location while only loading dependencies when needed:
```python
# In agent_framework/azure/__init__.py
# In agent_framework/foundry/__init__.py
_IMPORTS: dict[str, tuple[str, str]] = {
"AzureAIAgentClient": ("agent_framework_azure_ai", "agent-framework-azure-ai"),
"FoundryChatClient": ("agent_framework_foundry", "agent-framework-foundry"),
# ...
}
@@ -419,7 +420,7 @@ pip install agent-framework-core[all]
pip install agent-framework
# Install specific connector (pulls in core as dependency)
pip install agent-framework-azure-ai
pip install agent-framework-foundry
```
## Documentation
+1 -1
View File
@@ -249,7 +249,7 @@ For more advanced orchestration patterns including Sequential, Concurrent, Group
- [Getting Started with Agents](samples/02-agents): Basic agent creation and tool usage
- [Chat Client Examples](samples/02-agents/chat_client): Direct chat client usage patterns
- [Azure AI Integration](https://github.com/microsoft/agent-framework/tree/main/python/packages/azure-ai): Azure AI integration
- [Foundry Integration](https://github.com/microsoft/agent-framework/tree/main/python/packages/foundry): Microsoft Foundry integration
- [Workflow Samples](samples/03-workflows): Advanced multi-agent patterns
## Agent Framework Documentation
-30
View File
@@ -1,30 +0,0 @@
# Azure AI Package (agent-framework-azure-ai)
Integration with Azure AI inference embeddings plus shared Azure authentication helpers.
## Main Classes
- **`AzureAIInferenceEmbeddingClient`** - Full-featured Azure AI inference embeddings client
- **`RawAzureAIInferenceEmbeddingClient`** - Raw embeddings client without middleware layers
- **`AzureAIInferenceEmbeddingOptions`** / **`AzureAIInferenceEmbeddingSettings`** - Embedding options and settings
- **`AzureAISettings`** - Shared Azure AI project settings TypedDict
- **`AzureCredentialTypes`** / **`AzureTokenProvider`** - Shared Azure authentication helpers
## Usage
```python
from agent_framework_azure_ai import AzureAIInferenceEmbeddingClient
client = AzureAIInferenceEmbeddingClient(
endpoint="https://<resource>.inference.ai.azure.com",
api_key="...",
model="text-embedding-3-large",
)
result = await client.get_embeddings(["Hello"])
```
## Import Path
```python
from agent_framework_azure_ai import AzureAIInferenceEmbeddingClient
```
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
-26
View File
@@ -1,26 +0,0 @@
# Get Started with Microsoft Agent Framework Azure AI
Please install this package via pip:
```bash
pip install agent-framework-azure-ai --pre
```
## Foundry Memory Context Provider
The Foundry Memory context provider enables semantic memory capabilities for your agents using Azure AI Foundry Memory Store. It automatically:
- Retrieves static (user profile) memories on first run
- Searches for contextual memories based on conversation
- Updates the memory store with new conversation messages
### Basic Usage Example
See the [Foundry Memory example](../../samples/02-agents/context_providers/azure_ai_foundry_memory.py) which demonstrates:
- Creating a memory store using Azure AI Projects client
- Setting up an agent with FoundryMemoryProvider
- Teaching the agent user preferences
- Retrieving information using remembered context across conversations
- Automatic memory updates with configurable delays
and see the [README](https://github.com/microsoft/agent-framework/tree/main/python/README.md) for more information.
@@ -1,28 +0,0 @@
# Copyright (c) Microsoft. All rights reserved.
import importlib.metadata
from ._embedding_client import (
AzureAIInferenceEmbeddingClient,
AzureAIInferenceEmbeddingOptions,
AzureAIInferenceEmbeddingSettings,
RawAzureAIInferenceEmbeddingClient,
)
from ._entra_id_authentication import AzureCredentialTypes, AzureTokenProvider
from ._shared import AzureAISettings
try:
__version__ = importlib.metadata.version(__name__)
except importlib.metadata.PackageNotFoundError:
__version__ = "0.0.0"
__all__ = [
"AzureAIInferenceEmbeddingClient",
"AzureAIInferenceEmbeddingOptions",
"AzureAIInferenceEmbeddingSettings",
"AzureAISettings",
"AzureCredentialTypes",
"AzureTokenProvider",
"RawAzureAIInferenceEmbeddingClient",
"__version__",
]
@@ -1,67 +0,0 @@
# Copyright (c) Microsoft. All rights reserved.
from __future__ import annotations
import logging
from collections.abc import Awaitable, Callable
from typing import Union
from agent_framework.exceptions import ChatClientInvalidAuthException
from azure.core.credentials import TokenCredential
from azure.core.credentials_async import AsyncTokenCredential
logger: logging.Logger = logging.getLogger(__name__)
AzureTokenProvider = Callable[[], Union[str, Awaitable[str]]]
"""A callable that returns a bearer token string, either synchronously or asynchronously."""
AzureCredentialTypes = Union[TokenCredential, AsyncTokenCredential]
"""Union of Azure credential types.
Accepts:
- ``TokenCredential`` — synchronous Azure credential (e.g. ``DefaultAzureCredential()``)
- ``AsyncTokenCredential`` — asynchronous Azure credential (e.g. ``azure.identity.aio.DefaultAzureCredential()``)
"""
def resolve_credential_to_token_provider(
credential: AzureCredentialTypes | AzureTokenProvider,
token_endpoint: str | None,
) -> AzureTokenProvider:
"""Convert an Azure credential or token provider into an ``ad_token_provider`` callable.
If the credential is already a callable token provider, it is returned as-is
(``token_endpoint`` is not required in this case).
If it is a ``TokenCredential`` or ``AsyncTokenCredential``, it is wrapped using
``azure.identity.get_bearer_token_provider`` (sync or async variant) which
handles token caching and automatic refresh.
Args:
credential: An Azure credential or token provider callable.
token_endpoint: The token scope/endpoint
(e.g. ``"https://cognitiveservices.azure.com/.default"``).
Required when ``credential`` is a ``TokenCredential`` or ``AsyncTokenCredential``.
Returns:
A callable that returns a bearer token string (sync or async).
Raises:
ServiceInvalidAuthError: If the token endpoint is empty when needed for credential wrapping.
"""
# Already a token provider callable (not a credential object) — use directly
if callable(credential) and not isinstance(credential, (TokenCredential, AsyncTokenCredential)):
return credential
if not token_endpoint:
raise ChatClientInvalidAuthException(
"A token endpoint must be provided either in settings, as an environment variable, or as an argument."
)
if isinstance(credential, AsyncTokenCredential):
from azure.identity.aio import get_bearer_token_provider as get_async_bearer_token_provider
return get_async_bearer_token_provider(credential, token_endpoint)
from azure.identity import get_bearer_token_provider
return get_bearer_token_provider(credential, token_endpoint) # type: ignore[arg-type]
@@ -1,48 +0,0 @@
# Copyright (c) Microsoft. All rights reserved.
from __future__ import annotations
import sys
if sys.version_info >= (3, 11):
from typing import TypedDict # pragma: no cover
else:
from typing_extensions import TypedDict # type: ignore # pragma: no cover
class AzureAISettings(TypedDict, total=False):
"""Azure AI Project settings.
Settings are resolved in this order: explicit keyword arguments, values from an
explicitly provided .env file, then environment variables with the prefix
'AZURE_AI_'. If settings are missing after resolution, validation will fail.
Keyword Args:
project_endpoint: The Azure AI Project endpoint URL.
Can be set via environment variable AZURE_AI_PROJECT_ENDPOINT.
model: The name of the model to use.
Can be set via environment variable AZURE_AI_MODEL.
env_file_path: If provided, the .env settings are read from this file path location.
env_file_encoding: The encoding of the .env file, defaults to 'utf-8'.
Examples:
.. code-block:: python
from agent_framework.azure import AzureAISettings
# Using environment variables
# Set AZURE_AI_PROJECT_ENDPOINT=https://your-project.cognitiveservices.azure.com
# Set AZURE_AI_MODEL=gpt-4
settings = AzureAISettings()
# Or passing parameters directly
settings = AzureAISettings(
project_endpoint="https://your-project.cognitiveservices.azure.com", model="gpt-4"
)
# Or loading from a .env file
settings = AzureAISettings(env_file_path="path/to/.env")
"""
project_endpoint: str | None
model: str | None
-109
View File
@@ -1,109 +0,0 @@
[project]
name = "agent-framework-azure-ai"
description = "Azure AI Foundry integration for Microsoft Agent Framework."
authors = [{ name = "Microsoft", email = "af-support@microsoft.com"}]
readme = "README.md"
requires-python = ">=3.10"
version = "1.0.0rc6"
license-files = ["LICENSE"]
urls.homepage = "https://aka.ms/agent-framework"
urls.source = "https://github.com/microsoft/agent-framework/tree/main/python"
urls.release_notes = "https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true"
urls.issues = "https://github.com/microsoft/agent-framework/issues"
classifiers = [
"License :: OSI Approved :: MIT License",
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Typing :: Typed",
]
dependencies = [
"agent-framework-core>=1.0.0rc6",
"agent-framework-openai>=1.0.0rc6",
"azure-ai-projects>=2.0.0,<3.0",
"azure-ai-agents>=1.2.0b5,<1.2.0b6",
"azure-ai-inference>=1.0.0b9,<1.0.0b10",
"azure-identity>=1,<2",
"aiohttp>=3.7.0,<4",
]
[tool.uv]
prerelease = "if-necessary-or-explicit"
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
"sys_platform == 'win32'"
]
[tool.uv-dynamic-versioning]
fallback-version = "0.0.0"
[tool.pytest.ini_options]
testpaths = 'tests'
addopts = "-ra -q -r fEX"
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
filterwarnings = []
timeout = 120
markers = [
"integration: marks tests as integration tests that require external services",
]
[tool.ruff]
extend = "../../pyproject.toml"
[tool.coverage.run]
omit = [
"**/__init__.py"
]
[tool.pyright]
extends = "../../pyproject.toml"
include = ["agent_framework_azure_ai"]
[tool.mypy]
plugins = ['pydantic.mypy']
strict = true
python_version = "3.10"
ignore_missing_imports = true
disallow_untyped_defs = true
no_implicit_optional = true
check_untyped_defs = true
warn_return_any = true
show_error_codes = true
warn_unused_ignores = false
disallow_incomplete_defs = true
disallow_untyped_decorators = true
[tool.bandit]
targets = ["agent_framework_azure_ai"]
exclude_dirs = ["tests"]
[tool.poe]
executor.type = "uv"
include = "../../shared_tasks.toml"
[tool.poe.tasks.mypy]
help = "Run MyPy for this package."
cmd = "mypy --config-file $POE_ROOT/pyproject.toml agent_framework_azure_ai"
[tool.poe.tasks.test]
help = "Run the default unit test suite for this package."
cmd = 'pytest -m "not integration" --cov=agent_framework_azure_ai --cov-report=term-missing:skip-covered tests'
[tool.poe.tasks.integration-tests]
help = "Run the package integration test suite."
cmd = """
pytest --import-mode=importlib
-n logical --dist worksteal
tests
"""
[build-system]
requires = ["flit-core >= 3.11,<4.0"]
build-backend = "flit_core.buildapi"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

@@ -1,61 +0,0 @@
# Copyright (c) Microsoft. All rights reserved.
from unittest.mock import MagicMock, patch
import pytest
from agent_framework.exceptions import ChatClientInvalidAuthException
from azure.core.credentials import TokenCredential
from azure.core.credentials_async import AsyncTokenCredential
from agent_framework_azure_ai._entra_id_authentication import (
resolve_credential_to_token_provider,
)
TOKEN_ENDPOINT = "https://cognitiveservices.azure.com/.default"
def test_resolve_sync_credential_returns_provider() -> None:
"""Test that a sync TokenCredential is resolved via azure.identity.get_bearer_token_provider."""
mock_credential = MagicMock(spec=TokenCredential)
mock_provider = MagicMock(return_value="token-string")
with patch("azure.identity.get_bearer_token_provider", return_value=mock_provider) as mock_gbtp:
result = resolve_credential_to_token_provider(mock_credential, TOKEN_ENDPOINT)
mock_gbtp.assert_called_once_with(mock_credential, TOKEN_ENDPOINT)
assert result is mock_provider
def test_resolve_async_credential_returns_provider() -> None:
"""Test that an AsyncTokenCredential is resolved via azure.identity.aio.get_bearer_token_provider."""
mock_credential = MagicMock(spec=AsyncTokenCredential)
mock_provider = MagicMock(return_value="token-string")
with patch("azure.identity.aio.get_bearer_token_provider", return_value=mock_provider) as mock_gbtp:
result = resolve_credential_to_token_provider(mock_credential, TOKEN_ENDPOINT)
mock_gbtp.assert_called_once_with(mock_credential, TOKEN_ENDPOINT)
assert result is mock_provider
def test_resolve_callable_provider_passthrough() -> None:
"""Test that a callable token provider is returned as-is, without needing token_endpoint."""
my_provider = lambda: "my-token" # noqa: E731
# Works with token_endpoint
assert resolve_credential_to_token_provider(my_provider, TOKEN_ENDPOINT) is my_provider
# Also works without token_endpoint
assert resolve_credential_to_token_provider(my_provider, None) is my_provider
assert resolve_credential_to_token_provider(my_provider, "") is my_provider
def test_resolve_missing_endpoint_raises() -> None:
"""Test that missing token endpoint raises ChatClientInvalidAuthException."""
mock_credential = MagicMock(spec=TokenCredential)
with pytest.raises(ChatClientInvalidAuthException, match="A token endpoint must be provided"):
resolve_credential_to_token_provider(mock_credential, "")
with pytest.raises(ChatClientInvalidAuthException, match="A token endpoint must be provided"):
resolve_credential_to_token_provider(mock_credential, None) # type: ignore[arg-type]
@@ -1,78 +0,0 @@
# Copyright (c) Microsoft. All rights reserved.
from typing import Any
from unittest.mock import AsyncMock, MagicMock
from pytest import fixture
@fixture
def exclude_list(request: Any) -> list[str]:
"""Fixture that returns a list of environment variables to exclude."""
return request.param if hasattr(request, "param") else []
@fixture
def override_env_param_dict(request: Any) -> dict[str, str]:
"""Fixture that returns a dict of environment variables to override."""
return request.param if hasattr(request, "param") else {}
@fixture()
def azure_ai_unit_test_env(monkeypatch, exclude_list, override_env_param_dict): # type: ignore
"""Fixture to set environment variables for AzureAISettings."""
if exclude_list is None:
exclude_list = []
if override_env_param_dict is None:
override_env_param_dict = {}
env_vars = {
"AZURE_AI_PROJECT_ENDPOINT": "https://test-project.cognitiveservices.azure.com/",
"AZURE_AI_MODEL": "test-gpt-4o",
}
env_vars.update(override_env_param_dict) # type: ignore
for key, value in env_vars.items():
if key in exclude_list:
monkeypatch.delenv(key, raising=False) # type: ignore
continue
monkeypatch.setenv(key, value) # type: ignore
return env_vars
@fixture
def mock_agents_client() -> MagicMock:
"""Fixture that provides a mock AgentsClient."""
mock_client = MagicMock()
# Mock agents property
mock_client.create_agent = AsyncMock()
mock_client.delete_agent = AsyncMock()
# Mock agent creation response
mock_agent = MagicMock()
mock_agent.id = "test-agent-id"
mock_client.create_agent.return_value = mock_agent
# Mock threads property
mock_client.threads = MagicMock()
mock_client.threads.create = AsyncMock()
mock_client.messages.create = AsyncMock()
# Mock runs property
mock_client.runs = MagicMock()
mock_client.runs.list = AsyncMock()
mock_client.runs.cancel = AsyncMock()
mock_client.runs.stream = AsyncMock()
mock_client.runs.submit_tool_outputs_stream = AsyncMock()
return mock_client
@fixture
def mock_azure_credential() -> MagicMock:
"""Fixture that provides a mock AsyncTokenCredential."""
return MagicMock()
@@ -1,76 +0,0 @@
%PDF-1.7
%
1 0 obj
<</Type/Catalog/Pages 2 0 R/Lang(en) /StructTreeRoot 22 0 R/MarkInfo<</Marked true>>/Metadata 132 0 R/ViewerPreferences 133 0 R>>
endobj
2 0 obj
<</Type/Pages/Count 1/Kids[ 4 0 R] >>
endobj
3 0 obj
<</Author(Test Author) /Creator(Test Creator) /Title(Employee Directory) >>
endobj
4 0 obj
<</Type/Page/Parent 2 0 R/MediaBox[0 0 612 792]/Resources<</Font<</F1 5 0 R>>>>/Contents 6 0 R>>
endobj
5 0 obj
<</Type/Font/Subtype/Type1/BaseFont/Times-Roman>>
endobj
6 0 obj
<</Length 200>>
stream
BT
/F1 12 Tf
50 750 Td
(Employee Directory) Tj
0 -30 Td
(Name: John Smith) Tj
0 -15 Td
(Department: Engineering) Tj
0 -15 Td
(Age: 28) Tj
0 -30 Td
(Name: Alice Johnson) Tj
0 -15 Td
(Department: Sales) Tj
0 -15 Td
(Age: 24) Tj
0 -30 Td
(Name: Bob Wilson) Tj
0 -15 Td
(Department: Marketing) Tj
0 -15 Td
(Age: 35) Tj
ET
endstream
endobj
22 0 obj
<</Type/StructTreeRoot>>
endobj
132 0 obj
<</Type/Metadata/Subtype/XML>>
endobj
133 0 obj
<</DisplayDocTitle true>>
endobj
xref
0 10
0000000000 65535 f
0000000015 00000 n
0000000152 00000 n
0000000209 00000 n
0000000300 00000 n
0000000420 00000 n
0000000490 00000 n
0000000000 65535 f
0000000000 65535 f
0000000000 65535 f
22 1
0000000740 00000 n
132 2
0000000780 00000 n
0000000820 00000 n
trailer
<</Size 134/Root 1 0 R/Info 3 0 R>>
startxref
860
%%EOF
+3 -1
View File
@@ -9,7 +9,7 @@ Azure Cosmos DB history provider integration for Agent Framework.
## Usage
```python
from agent_framework_azure_cosmos import CosmosHistoryProvider
from agent_framework.azure import CosmosHistoryProvider
provider = CosmosHistoryProvider(
endpoint="https://<account>.documents.azure.com:443/",
@@ -24,5 +24,7 @@ Container name is configured on the provider. `session_id` is used as the partit
## Import Path
```python
from agent_framework.azure import CosmosHistoryProvider
# or directly:
from agent_framework_azure_cosmos import CosmosHistoryProvider
```
+11 -2
View File
@@ -14,7 +14,7 @@ The Azure Cosmos DB integration provides `CosmosHistoryProvider` for persistent
```python
from azure.identity.aio import DefaultAzureCredential
from agent_framework_azure_cosmos import CosmosHistoryProvider
from agent_framework.azure import CosmosHistoryProvider
provider = CosmosHistoryProvider(
endpoint="https://<account>.documents.azure.com:443/",
@@ -35,4 +35,13 @@ Container naming behavior:
- Container name is configured on the provider (`container_name` or `AZURE_COSMOS_CONTAINER_NAME`)
- `session_id` is used as the Cosmos partition key for reads/writes
See `samples/cosmos_history_provider.py` for a runnable package-local example.
See the [conversation samples](../../samples/02-agents/conversations/) for runnable examples, including
[`cosmos_history_provider.py`](../../samples/02-agents/conversations/cosmos_history_provider.py).
## Import Paths
```python
from agent_framework.azure import CosmosHistoryProvider
# or directly:
from agent_framework_azure_cosmos import CosmosHistoryProvider
```
@@ -1,20 +0,0 @@
# Azure Cosmos DB Package Samples
This folder contains samples for `agent-framework-azure-cosmos`.
| File | Description |
| --- | --- |
| [`cosmos_history_provider.py`](cosmos_history_provider.py) | Demonstrates an Agent using `CosmosHistoryProvider` with `FoundryChatClient` (configured against an Azure AI Foundry project endpoint), provider-configured container name, and `session_id` partitioning. |
## Prerequisites
- `AZURE_COSMOS_ENDPOINT`
- `AZURE_COSMOS_DATABASE_NAME`
- `AZURE_COSMOS_CONTAINER_NAME`
- `AZURE_COSMOS_KEY` (or equivalent credential flow)
## Run
```bash
uv run --directory packages/azure-cosmos python samples/cosmos_history_provider.py
```
@@ -1,3 +0,0 @@
# Copyright (c) Microsoft. All rights reserved.
"""Samples for the Azure Cosmos history provider package."""
+1 -1
View File
@@ -34,8 +34,8 @@ FOUNDRY_PROJECT_ENDPOINT=...
FOUNDRY_MODEL=...
...
OPENAI_API_KEY=sk-...
OPENAI_CHAT_COMPLETION_MODEL=...
OPENAI_CHAT_MODEL=...
OPENAI_RESPONSES_MODEL=...
...
AZURE_OPENAI_API_KEY=...
AZURE_OPENAI_ENDPOINT=...
@@ -14,13 +14,7 @@ _IMPORTS: dict[str, tuple[str, str]] = {
"AgentResponseCallbackProtocol": ("agent_framework_durabletask", "agent-framework-durabletask"),
"AzureAISearchContextProvider": ("agent_framework_azure_ai_search", "agent-framework-azure-ai-search"),
"AzureAISearchSettings": ("agent_framework_azure_ai_search", "agent-framework-azure-ai-search"),
"AzureAISettings": ("agent_framework_azure_ai", "agent-framework-azure-ai"),
"AzureAIInferenceEmbeddingClient": ("agent_framework_azure_ai", "agent-framework-azure-ai"),
"AzureAIInferenceEmbeddingOptions": ("agent_framework_azure_ai", "agent-framework-azure-ai"),
"AzureAIInferenceEmbeddingSettings": ("agent_framework_azure_ai", "agent-framework-azure-ai"),
"RawAzureAIInferenceEmbeddingClient": ("agent_framework_azure_ai", "agent-framework-azure-ai"),
"AzureCredentialTypes": ("agent_framework_azure_ai", "agent-framework-azure-ai"),
"AzureTokenProvider": ("agent_framework_azure_ai", "agent-framework-azure-ai"),
"CosmosHistoryProvider": ("agent_framework_azure_cosmos", "agent-framework-azure-cosmos"),
"DurableAIAgent": ("agent_framework_durabletask", "agent-framework-durabletask"),
"DurableAIAgentClient": ("agent_framework_durabletask", "agent-framework-durabletask"),
"DurableAIAgentOrchestrationContext": ("agent_framework_durabletask", "agent-framework-durabletask"),
@@ -3,19 +3,11 @@
# Type stubs for the agent_framework.azure lazy-loading namespace.
# Install the relevant packages for full type support.
from agent_framework_azure_ai import (
AzureAIInferenceEmbeddingClient,
AzureAIInferenceEmbeddingOptions,
AzureAIInferenceEmbeddingSettings,
AzureAISettings,
AzureCredentialTypes,
AzureTokenProvider,
RawAzureAIInferenceEmbeddingClient,
)
from agent_framework_azure_ai_search import (
AzureAISearchContextProvider,
AzureAISearchSettings,
)
from agent_framework_azure_cosmos import CosmosHistoryProvider
from agent_framework_azurefunctions import AgentFunctionApp
from agent_framework_durabletask import (
AgentCallbackContext,
@@ -30,17 +22,11 @@ __all__ = [
"AgentCallbackContext",
"AgentFunctionApp",
"AgentResponseCallbackProtocol",
"AzureAIInferenceEmbeddingClient",
"AzureAIInferenceEmbeddingOptions",
"AzureAIInferenceEmbeddingSettings",
"AzureAISearchContextProvider",
"AzureAISearchSettings",
"AzureAISettings",
"AzureCredentialTypes",
"AzureTokenProvider",
"CosmosHistoryProvider",
"DurableAIAgent",
"DurableAIAgentClient",
"DurableAIAgentOrchestrationContext",
"DurableAIAgentWorker",
"RawAzureAIInferenceEmbeddingClient",
]
@@ -16,6 +16,9 @@ _IMPORTS: dict[str, tuple[str, str]] = {
"FoundryAgent": ("agent_framework_foundry", "agent-framework-foundry"),
"FoundryChatClient": ("agent_framework_foundry", "agent-framework-foundry"),
"FoundryChatOptions": ("agent_framework_foundry", "agent-framework-foundry"),
"FoundryEmbeddingClient": ("agent_framework_foundry", "agent-framework-foundry"),
"FoundryEmbeddingOptions": ("agent_framework_foundry", "agent-framework-foundry"),
"FoundryEmbeddingSettings": ("agent_framework_foundry", "agent-framework-foundry"),
"FoundryEvals": ("agent_framework_foundry", "agent-framework-foundry"),
"FoundryMemoryProvider": ("agent_framework_foundry", "agent-framework-foundry"),
"FoundryLocalChatOptions": ("agent_framework_foundry_local", "agent-framework-foundry-local"),
@@ -25,6 +28,7 @@ _IMPORTS: dict[str, tuple[str, str]] = {
"RawFoundryAgent": ("agent_framework_foundry", "agent-framework-foundry"),
"RawFoundryAgentChatClient": ("agent_framework_foundry", "agent-framework-foundry"),
"RawFoundryChatClient": ("agent_framework_foundry", "agent-framework-foundry"),
"RawFoundryEmbeddingClient": ("agent_framework_foundry", "agent-framework-foundry"),
"evaluate_foundry_target": ("agent_framework_foundry", "agent-framework-foundry"),
"evaluate_traces": ("agent_framework_foundry", "agent-framework-foundry"),
}
@@ -8,11 +8,15 @@ from agent_framework_foundry import (
FoundryAgent,
FoundryChatClient,
FoundryChatOptions,
FoundryEmbeddingClient,
FoundryEmbeddingOptions,
FoundryEmbeddingSettings,
FoundryEvals,
FoundryMemoryProvider,
RawFoundryAgent,
RawFoundryAgentChatClient,
RawFoundryChatClient,
RawFoundryEmbeddingClient,
evaluate_foundry_target,
evaluate_traces,
)
@@ -27,6 +31,9 @@ __all__ = [
"FoundryAgent",
"FoundryChatClient",
"FoundryChatOptions",
"FoundryEmbeddingClient",
"FoundryEmbeddingOptions",
"FoundryEmbeddingSettings",
"FoundryEvals",
"FoundryLocalChatOptions",
"FoundryLocalClient",
@@ -36,6 +43,7 @@ __all__ = [
"RawFoundryAgent",
"RawFoundryAgentChatClient",
"RawFoundryChatClient",
"RawFoundryEmbeddingClient",
"evaluate_foundry_target",
"evaluate_traces",
]
@@ -5,7 +5,6 @@
This module lazily re-exports objects from:
- ``agent-framework-copilotstudio``
- ``agent-framework-purview``
- ``agent-framework-foundry-local``
Supported classes:
- CopilotStudioAgent
@@ -20,9 +19,6 @@ Supported classes:
- PurviewRequestError
- PurviewServiceError
- CacheProvider
- FoundryLocalChatOptions
- FoundryLocalClient
- FoundryLocalSettings
"""
@@ -43,9 +39,6 @@ _IMPORTS: dict[str, tuple[str, str]] = {
"PurviewRequestError": ("agent_framework_purview", "agent-framework-purview"),
"PurviewServiceError": ("agent_framework_purview", "agent-framework-purview"),
"CacheProvider": ("agent_framework_purview", "agent-framework-purview"),
"FoundryLocalChatOptions": ("agent_framework_foundry_local", "agent-framework-foundry-local"),
"FoundryLocalClient": ("agent_framework_foundry_local", "agent-framework-foundry-local"),
"FoundryLocalSettings": ("agent_framework_foundry_local", "agent-framework-foundry-local"),
}
@@ -4,11 +4,6 @@ from agent_framework_copilotstudio import (
CopilotStudioAgent,
acquire_token,
)
from agent_framework_foundry_local import (
FoundryLocalChatOptions,
FoundryLocalClient,
FoundryLocalSettings,
)
from agent_framework_purview import (
CacheProvider,
PurviewAppLocation,
@@ -26,9 +21,6 @@ from agent_framework_purview import (
__all__ = [
"CacheProvider",
"CopilotStudioAgent",
"FoundryLocalChatOptions",
"FoundryLocalClient",
"FoundryLocalSettings",
"PurviewAppLocation",
"PurviewAuthenticationError",
"PurviewChatPolicyMiddleware",
+1 -1
View File
@@ -35,10 +35,10 @@ all = [
"agent-framework-a2a",
"agent-framework-ag-ui",
"agent-framework-azure-ai-search",
"agent-framework-azure-cosmos",
"agent-framework-anthropic",
"agent-framework-openai",
"agent-framework-claude",
"agent-framework-azure-ai",
"agent-framework-azurefunctions",
"agent-framework-bedrock",
"agent-framework-chatkit",
@@ -0,0 +1,10 @@
# Copyright (c) Microsoft. All rights reserved.
from agent_framework_azure_cosmos import CosmosHistoryProvider
import agent_framework.azure as azure
def test_azure_namespace_exposes_cosmos_history_provider() -> None:
assert azure.CosmosHistoryProvider is CosmosHistoryProvider
assert "CosmosHistoryProvider" in dir(azure)
@@ -481,7 +481,7 @@ services:
environment:
# OpenAI
- OPENAI_API_KEY=\${OPENAI_API_KEY}
- OPENAI_CHAT_MODEL=\${OPENAI_CHAT_MODEL:-gpt-4o-mini}
- OPENAI_CHAT_COMPLETION_MODEL=\${OPENAI_CHAT_COMPLETION_MODEL:-gpt-4o-mini}
# Or Azure OpenAI
- AZURE_OPENAI_API_KEY=\${AZURE_OPENAI_API_KEY}
- AZURE_OPENAI_ENDPOINT=\${AZURE_OPENAI_ENDPOINT}
@@ -514,7 +514,7 @@ az acr build --registry myregistry \\
--target-port 8080 \\
--ingress 'external' \\
--registry-server myregistry.azurecr.io \\
--env-vars OPENAI_API_KEY=secretref:openai-key OPENAI_CHAT_MODEL=gpt-4o-mini`})]
--env-vars OPENAI_API_KEY=secretref:openai-key OPENAI_CHAT_COMPLETION_MODEL=gpt-4o-mini`})]
}), o.jsxs("div", {
className: "border-l-2 border-primary pl-3", children: [o.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [o.jsx("div", { className: "w-5 h-5 rounded-full bg-primary text-primary-foreground flex items-center justify-center text-xs font-bold", children: "5" }), o.jsx("h5", { className: "font-medium text-sm", children: "Get Application URL" })] }), o.jsx("pre", {
className: "bg-muted p-2 rounded text-xs overflow-x-auto border mt-2", children: `az containerapp show --name ${r.toLowerCase()}-app \\
+1 -1
View File
@@ -33,7 +33,7 @@ Then edit `.env` and add your API keys:
```bash
# For OpenAI (minimum required)
OPENAI_API_KEY="your-api-key-here"
OPENAI_CHAT_MODEL="gpt-4o-mini"
OPENAI_CHAT_COMPLETION_MODEL="gpt-4o-mini"
# Or for Azure OpenAI
AZURE_OPENAI_ENDPOINT="your-endpoint"
@@ -243,7 +243,7 @@ services:
environment:
# OpenAI
- OPENAI_API_KEY=\${OPENAI_API_KEY}
- OPENAI_CHAT_MODEL=\${OPENAI_CHAT_MODEL:-gpt-4o-mini}
- OPENAI_CHAT_COMPLETION_MODEL=\${OPENAI_CHAT_COMPLETION_MODEL:-gpt-4o-mini}
# Or Azure OpenAI
- AZURE_OPENAI_API_KEY=\${AZURE_OPENAI_API_KEY}
- AZURE_OPENAI_ENDPOINT=\${AZURE_OPENAI_ENDPOINT}
@@ -802,7 +802,7 @@ az acr build --registry myregistry \\
--target-port 8080 \\
--ingress 'external' \\
--registry-server myregistry.azurecr.io \\
--env-vars OPENAI_API_KEY=secretref:openai-key OPENAI_CHAT_MODEL=gpt-4o-mini`}
--env-vars OPENAI_API_KEY=secretref:openai-key OPENAI_CHAT_COMPLETION_MODEL=gpt-4o-mini`}
</pre>
</div>
+1 -1
View File
@@ -1,3 +1,3 @@
# Agent Framework Foundry
This package contains the cloud Azure AI Foundry integrations for Microsoft Agent Framework, including Foundry chat clients, preconfigured Foundry agents, and Foundry memory providers.
This package contains the Microsoft Foundry integrations for Microsoft Agent Framework, including Foundry chat clients, preconfigured Foundry agents, Foundry embedding clients, and Foundry memory providers.
@@ -4,6 +4,12 @@ import importlib.metadata
from ._agent import FoundryAgent, RawFoundryAgent, RawFoundryAgentChatClient
from ._chat_client import FoundryChatClient, FoundryChatOptions, RawFoundryChatClient
from ._embedding_client import (
FoundryEmbeddingClient,
FoundryEmbeddingOptions,
FoundryEmbeddingSettings,
RawFoundryEmbeddingClient,
)
from ._foundry_evals import (
FoundryEvals,
evaluate_foundry_target,
@@ -20,11 +26,15 @@ __all__ = [
"FoundryAgent",
"FoundryChatClient",
"FoundryChatOptions",
"FoundryEmbeddingClient",
"FoundryEmbeddingOptions",
"FoundryEmbeddingSettings",
"FoundryEvals",
"FoundryMemoryProvider",
"RawFoundryAgent",
"RawFoundryAgentChatClient",
"RawFoundryChatClient",
"RawFoundryEmbeddingClient",
"__version__",
"evaluate_foundry_target",
"evaluate_traces",
@@ -28,22 +28,22 @@ else:
from typing_extensions import TypeVar # type: ignore # pragma: no cover
logger = logging.getLogger("agent_framework.azure_ai")
logger = logging.getLogger("agent_framework.foundry")
_IMAGE_MEDIA_PREFIXES = ("image/",)
class AzureAIInferenceEmbeddingOptions(EmbeddingGenerationOptions, total=False):
"""Azure AI Inference-specific embedding options.
class FoundryEmbeddingOptions(EmbeddingGenerationOptions, total=False):
"""Foundry inference-specific embedding options.
Extends EmbeddingGenerationOptions with Azure AI Inference-specific fields.
Extends ``EmbeddingGenerationOptions`` with Foundry inference-specific fields.
Examples:
.. code-block:: python
from agent_framework_azure_ai import AzureAIInferenceEmbeddingOptions
from agent_framework_foundry import FoundryEmbeddingOptions
options: AzureAIInferenceEmbeddingOptions = {
options: FoundryEmbeddingOptions = {
"model": "text-embedding-3-small",
"dimensions": 1536,
"input_type": "document",
@@ -68,28 +68,28 @@ class AzureAIInferenceEmbeddingOptions(EmbeddingGenerationOptions, total=False):
"""Additional model-specific parameters passed directly to the API."""
AzureAIInferenceEmbeddingOptionsT = TypeVar(
"AzureAIInferenceEmbeddingOptionsT",
FoundryEmbeddingOptionsT = TypeVar(
"FoundryEmbeddingOptionsT",
bound=TypedDict, # type: ignore[valid-type]
default="AzureAIInferenceEmbeddingOptions",
default="FoundryEmbeddingOptions",
covariant=True,
)
class AzureAIInferenceEmbeddingSettings(TypedDict, total=False):
"""Azure AI Inference embedding settings."""
class FoundryEmbeddingSettings(TypedDict, total=False):
"""Foundry inference embedding settings."""
endpoint: str | None
api_key: str | None
models_endpoint: str | None
models_api_key: str | None
embedding_model: str | None
image_embedding_model: str | None
class RawAzureAIInferenceEmbeddingClient(
BaseEmbeddingClient[Content | str, list[float], AzureAIInferenceEmbeddingOptionsT],
Generic[AzureAIInferenceEmbeddingOptionsT],
class RawFoundryEmbeddingClient(
BaseEmbeddingClient[Content | str, list[float], FoundryEmbeddingOptionsT],
Generic[FoundryEmbeddingOptionsT],
):
"""Raw Azure AI Inference embedding client without telemetry.
"""Raw Foundry embedding client without telemetry.
Accepts both text (``str``) and image (``Content``) inputs. Text and image
inputs within a single batch are separated and dispatched to
@@ -98,14 +98,14 @@ class RawAzureAIInferenceEmbeddingClient(
Keyword Args:
model: The text embedding model (e.g. "text-embedding-3-small").
Can also be set via environment variable AZURE_AI_INFERENCE_EMBEDDING_MODEL.
Can also be set via environment variable FOUNDRY_EMBEDDING_MODEL.
image_model: The image embedding model (e.g. "Cohere-embed-v3-english").
Can also be set via environment variable AZURE_AI_INFERENCE_IMAGE_EMBEDDING_MODEL.
Can also be set via environment variable FOUNDRY_IMAGE_EMBEDDING_MODEL.
Falls back to ``model`` if not provided.
endpoint: The Azure AI Inference endpoint URL.
Can also be set via environment variable AZURE_AI_INFERENCE_ENDPOINT.
endpoint: The Foundry inference endpoint URL.
Can also be set via environment variable FOUNDRY_MODELS_ENDPOINT.
api_key: API key for authentication.
Can also be set via environment variable AZURE_AI_INFERENCE_API_KEY.
Can also be set via environment variable FOUNDRY_MODELS_API_KEY.
text_client: Optional pre-configured ``EmbeddingsClient``.
image_client: Optional pre-configured ``ImageEmbeddingsClient``.
credential: Optional ``AzureKeyCredential`` or token credential. If not provided,
@@ -128,13 +128,13 @@ class RawAzureAIInferenceEmbeddingClient(
env_file_path: str | None = None,
env_file_encoding: str | None = None,
) -> None:
"""Initialize a raw Azure AI Inference embedding client."""
"""Initialize a raw Foundry embedding client."""
settings = load_settings(
AzureAIInferenceEmbeddingSettings,
env_prefix="AZURE_AI_INFERENCE_",
required_fields=["endpoint", "embedding_model"],
endpoint=endpoint,
api_key=api_key,
FoundryEmbeddingSettings,
env_prefix="FOUNDRY_",
required_fields=["models_endpoint", "embedding_model"],
models_endpoint=endpoint,
models_api_key=api_key,
embedding_model=model,
image_embedding_model=image_model,
env_file_path=env_file_path,
@@ -143,10 +143,10 @@ class RawAzureAIInferenceEmbeddingClient(
self.model = settings["embedding_model"] # type: ignore[reportTypedDictNotRequiredAccess]
self.image_model: str = settings.get("image_embedding_model") or self.model # type: ignore[assignment]
resolved_endpoint = settings["endpoint"] # type: ignore[reportTypedDictNotRequiredAccess]
resolved_endpoint = settings["models_endpoint"] # type: ignore[reportTypedDictNotRequiredAccess]
if credential is None and settings.get("api_key"):
credential = AzureKeyCredential(settings["api_key"]) # type: ignore[arg-type]
if credential is None and settings.get("models_api_key"):
credential = AzureKeyCredential(settings["models_api_key"]) # type: ignore[arg-type]
if credential is None and text_client is None and image_client is None:
raise ValueError("Either 'api_key', 'credential', or pre-configured client(s) must be provided.")
@@ -169,7 +169,7 @@ class RawAzureAIInferenceEmbeddingClient(
with suppress(Exception):
await self._image_client.close()
async def __aenter__(self) -> RawAzureAIInferenceEmbeddingClient[AzureAIInferenceEmbeddingOptionsT]:
async def __aenter__(self) -> RawFoundryEmbeddingClient[FoundryEmbeddingOptionsT]:
"""Enter the async context manager."""
return self
@@ -185,8 +185,8 @@ class RawAzureAIInferenceEmbeddingClient(
self,
values: Sequence[Content | str],
*,
options: AzureAIInferenceEmbeddingOptionsT | None = None,
) -> GeneratedEmbeddings[list[float], AzureAIInferenceEmbeddingOptionsT]:
options: FoundryEmbeddingOptionsT | None = None,
) -> GeneratedEmbeddings[list[float], FoundryEmbeddingOptionsT]:
"""Generate embeddings for text and/or image inputs.
Text inputs (``str`` or ``Content`` with ``type="text"``) are sent to the
@@ -310,12 +310,12 @@ class RawAzureAIInferenceEmbeddingClient(
) # type: ignore[reportReturnType]
class AzureAIInferenceEmbeddingClient(
EmbeddingTelemetryLayer[Content | str, list[float], AzureAIInferenceEmbeddingOptionsT],
RawAzureAIInferenceEmbeddingClient[AzureAIInferenceEmbeddingOptionsT],
Generic[AzureAIInferenceEmbeddingOptionsT],
class FoundryEmbeddingClient(
EmbeddingTelemetryLayer[Content | str, list[float], FoundryEmbeddingOptionsT],
RawFoundryEmbeddingClient[FoundryEmbeddingOptionsT],
Generic[FoundryEmbeddingOptionsT],
):
"""Azure AI Inference embedding client with telemetry support.
"""Foundry embedding client with telemetry support.
Supports both text and image inputs in a single client. Pass plain strings
or ``Content`` instances created with ``Content.from_text()`` or
@@ -323,14 +323,14 @@ class AzureAIInferenceEmbeddingClient(
Keyword Args:
model: The text embedding model (e.g. "text-embedding-3-small").
Can also be set via environment variable AZURE_AI_INFERENCE_EMBEDDING_MODEL.
Can also be set via environment variable FOUNDRY_EMBEDDING_MODEL.
image_model: The image embedding model
(e.g. "Cohere-embed-v3-english"). Can also be set via environment variable
AZURE_AI_INFERENCE_IMAGE_EMBEDDING_MODEL. Falls back to ``model``.
endpoint: The Azure AI Inference endpoint URL.
Can also be set via environment variable AZURE_AI_INFERENCE_ENDPOINT.
FOUNDRY_IMAGE_EMBEDDING_MODEL. Falls back to ``model``.
endpoint: The Foundry inference endpoint URL.
Can also be set via environment variable FOUNDRY_MODELS_ENDPOINT.
api_key: API key for authentication.
Can also be set via environment variable AZURE_AI_INFERENCE_API_KEY.
Can also be set via environment variable FOUNDRY_MODELS_API_KEY.
text_client: Optional pre-configured ``EmbeddingsClient``.
image_client: Optional pre-configured ``ImageEmbeddingsClient``.
credential: Optional ``AzureKeyCredential`` or token credential.
@@ -341,14 +341,14 @@ class AzureAIInferenceEmbeddingClient(
Examples:
.. code-block:: python
from agent_framework_azure_ai import AzureAIInferenceEmbeddingClient
from agent_framework_foundry import FoundryEmbeddingClient
# Using environment variables
# Set AZURE_AI_INFERENCE_ENDPOINT=https://your-endpoint.inference.ai.azure.com
# Set AZURE_AI_INFERENCE_API_KEY=your-key
# Set AZURE_AI_INFERENCE_EMBEDDING_MODEL=text-embedding-3-small
# Set AZURE_AI_INFERENCE_IMAGE_EMBEDDING_MODEL=Cohere-embed-v3-english
client = AzureAIInferenceEmbeddingClient()
# Set FOUNDRY_MODELS_ENDPOINT=https://your-endpoint.inference.ai.azure.com
# Set FOUNDRY_MODELS_API_KEY=your-key
# Set FOUNDRY_EMBEDDING_MODEL=text-embedding-3-small
# Set FOUNDRY_IMAGE_EMBEDDING_MODEL=Cohere-embed-v3-english
client = FoundryEmbeddingClient()
# Text embeddings
result = await client.get_embeddings(["Hello, world!"])
@@ -380,7 +380,7 @@ class AzureAIInferenceEmbeddingClient(
env_file_path: str | None = None,
env_file_encoding: str | None = None,
) -> None:
"""Initialize an Azure AI Inference embedding client."""
"""Initialize a Foundry embedding client."""
super().__init__(
model=model,
image_model=image_model,
+1
View File
@@ -25,6 +25,7 @@ classifiers = [
dependencies = [
"agent-framework-core>=1.0.0rc6",
"agent-framework-openai>=1.0.0rc6",
"azure-ai-inference>=1.0.0b9,<1.0.0b10",
"azure-ai-projects>=2.0.0,<3.0",
]
@@ -10,10 +10,10 @@ from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from agent_framework import Content
from agent_framework_azure_ai import (
AzureAIInferenceEmbeddingClient,
AzureAIInferenceEmbeddingOptions,
RawAzureAIInferenceEmbeddingClient,
from agent_framework_foundry import (
FoundryEmbeddingClient,
FoundryEmbeddingOptions,
RawFoundryEmbeddingClient,
)
@@ -57,9 +57,9 @@ def mock_image_client() -> AsyncMock:
@pytest.fixture
def raw_client(mock_text_client: AsyncMock, mock_image_client: AsyncMock) -> RawAzureAIInferenceEmbeddingClient[Any]:
"""Create a RawAzureAIInferenceEmbeddingClient with mocked SDK clients."""
return RawAzureAIInferenceEmbeddingClient(
def raw_client(mock_text_client: AsyncMock, mock_image_client: AsyncMock) -> RawFoundryEmbeddingClient[Any]:
"""Create a RawFoundryEmbeddingClient with mocked SDK clients."""
return RawFoundryEmbeddingClient(
model="test-model",
endpoint="https://test.inference.ai.azure.com",
api_key="test-key",
@@ -69,9 +69,9 @@ def raw_client(mock_text_client: AsyncMock, mock_image_client: AsyncMock) -> Raw
@pytest.fixture
def client(mock_text_client: AsyncMock, mock_image_client: AsyncMock) -> AzureAIInferenceEmbeddingClient[Any]:
"""Create an AzureAIInferenceEmbeddingClient with mocked SDK clients."""
return AzureAIInferenceEmbeddingClient(
def client(mock_text_client: AsyncMock, mock_image_client: AsyncMock) -> FoundryEmbeddingClient[Any]:
"""Create a FoundryEmbeddingClient with mocked SDK clients."""
return FoundryEmbeddingClient(
model="test-model",
endpoint="https://test.inference.ai.azure.com",
api_key="test-key",
@@ -80,11 +80,11 @@ def client(mock_text_client: AsyncMock, mock_image_client: AsyncMock) -> AzureAI
)
class TestRawAzureAIInferenceEmbeddingClient:
"""Tests for the raw Azure AI Inference embedding client."""
class TestRawFoundryEmbeddingClient:
"""Tests for the raw Foundry embedding client."""
async def test_text_embeddings(
self, raw_client: RawAzureAIInferenceEmbeddingClient[Any], mock_text_client: AsyncMock
self, raw_client: RawFoundryEmbeddingClient[Any], mock_text_client: AsyncMock
) -> None:
"""Text inputs are dispatched to the text client."""
result = await raw_client.get_embeddings(["hello", "world"])
@@ -94,7 +94,7 @@ class TestRawAzureAIInferenceEmbeddingClient:
assert call_kwargs.kwargs["model"] == "test-model"
async def test_text_content_embeddings(
self, raw_client: RawAzureAIInferenceEmbeddingClient[Any], mock_text_client: AsyncMock
self, raw_client: RawFoundryEmbeddingClient[Any], mock_text_client: AsyncMock
) -> None:
"""Content.from_text() inputs are dispatched to the text client."""
text_content = Content.from_text("hello")
@@ -105,7 +105,7 @@ class TestRawAzureAIInferenceEmbeddingClient:
assert call_kwargs.kwargs["input"] == ["hello"]
async def test_image_content_embeddings(
self, raw_client: RawAzureAIInferenceEmbeddingClient[Any], mock_image_client: AsyncMock
self, raw_client: RawFoundryEmbeddingClient[Any], mock_image_client: AsyncMock
) -> None:
"""Image Content inputs are dispatched to the image client."""
image_content = Content.from_data(data=b"\x89PNG", media_type="image/png")
@@ -119,7 +119,7 @@ class TestRawAzureAIInferenceEmbeddingClient:
async def test_mixed_text_and_image(
self,
raw_client: RawAzureAIInferenceEmbeddingClient[Any],
raw_client: RawFoundryEmbeddingClient[Any],
mock_text_client: AsyncMock,
mock_image_client: AsyncMock,
) -> None:
@@ -138,16 +138,16 @@ class TestRawAzureAIInferenceEmbeddingClient:
image_call = mock_image_client.embed.call_args
assert len(image_call.kwargs["input"]) == 1
async def test_empty_input(self, raw_client: RawAzureAIInferenceEmbeddingClient[Any]) -> None:
async def test_empty_input(self, raw_client: RawFoundryEmbeddingClient[Any]) -> None:
"""Empty input returns empty result."""
result = await raw_client.get_embeddings([])
assert len(result) == 0
async def test_options_passed_through(
self, raw_client: RawAzureAIInferenceEmbeddingClient[Any], mock_text_client: AsyncMock
self, raw_client: RawFoundryEmbeddingClient[Any], mock_text_client: AsyncMock
) -> None:
"""Options are passed through to the SDK."""
options: AzureAIInferenceEmbeddingOptions = {
options: FoundryEmbeddingOptions = {
"dimensions": 512,
"input_type": "document",
"encoding_format": "float",
@@ -160,23 +160,23 @@ class TestRawAzureAIInferenceEmbeddingClient:
assert call_kwargs.kwargs["encoding_format"] == "float"
async def test_model_override_in_options(
self, raw_client: RawAzureAIInferenceEmbeddingClient[Any], mock_text_client: AsyncMock
self, raw_client: RawFoundryEmbeddingClient[Any], mock_text_client: AsyncMock
) -> None:
"""model in options overrides the default."""
options: AzureAIInferenceEmbeddingOptions = {"model": "custom-model"}
options: FoundryEmbeddingOptions = {"model": "custom-model"}
await raw_client.get_embeddings(["hello"], options=options)
call_kwargs = mock_text_client.embed.call_args
assert call_kwargs.kwargs["model"] == "custom-model"
async def test_unsupported_content_type_raises(self, raw_client: RawAzureAIInferenceEmbeddingClient[Any]) -> None:
async def test_unsupported_content_type_raises(self, raw_client: RawFoundryEmbeddingClient[Any]) -> None:
"""Non-text, non-image Content raises ValueError."""
error_content = Content("error", message="fail")
with pytest.raises(ValueError, match="Unsupported Content type"):
await raw_client.get_embeddings([error_content])
async def test_usage_metadata(
self, raw_client: RawAzureAIInferenceEmbeddingClient[Any], mock_text_client: AsyncMock
self, raw_client: RawFoundryEmbeddingClient[Any], mock_text_client: AsyncMock
) -> None:
"""Usage metadata is populated from the response."""
mock_text_client.embed.return_value = _make_embed_response([[0.1, 0.2]], prompt_tokens=42)
@@ -184,7 +184,7 @@ class TestRawAzureAIInferenceEmbeddingClient:
assert result.usage is not None
assert result.usage["input_token_count"] == 42
def test_service_url(self, raw_client: RawAzureAIInferenceEmbeddingClient[Any]) -> None:
def test_service_url(self, raw_client: RawFoundryEmbeddingClient[Any]) -> None:
"""service_url returns the configured endpoint."""
assert raw_client.service_url() == "https://test.inference.ai.azure.com"
@@ -194,15 +194,15 @@ class TestRawAzureAIInferenceEmbeddingClient:
patch.dict(
os.environ,
{
"AZURE_AI_INFERENCE_ENDPOINT": "https://env.inference.ai.azure.com",
"AZURE_AI_INFERENCE_API_KEY": "env-key",
"AZURE_AI_INFERENCE_EMBEDDING_MODEL": "env-model",
"FOUNDRY_MODELS_ENDPOINT": "https://env.inference.ai.azure.com",
"FOUNDRY_MODELS_API_KEY": "env-key",
"FOUNDRY_EMBEDDING_MODEL": "env-model",
},
),
patch("agent_framework_azure_ai._embedding_client.EmbeddingsClient"),
patch("agent_framework_azure_ai._embedding_client.ImageEmbeddingsClient"),
patch("agent_framework_foundry._embedding_client.EmbeddingsClient"),
patch("agent_framework_foundry._embedding_client.ImageEmbeddingsClient"),
):
client = RawAzureAIInferenceEmbeddingClient()
client = RawFoundryEmbeddingClient()
assert client.model == "env-model"
assert client.image_model == "env-model" # falls back to model
@@ -212,22 +212,22 @@ class TestRawAzureAIInferenceEmbeddingClient:
patch.dict(
os.environ,
{
"AZURE_AI_INFERENCE_ENDPOINT": "https://env.inference.ai.azure.com",
"AZURE_AI_INFERENCE_API_KEY": "env-key",
"AZURE_AI_INFERENCE_EMBEDDING_MODEL": "text-model",
"AZURE_AI_INFERENCE_IMAGE_EMBEDDING_MODEL": "image-model",
"FOUNDRY_MODELS_ENDPOINT": "https://env.inference.ai.azure.com",
"FOUNDRY_MODELS_API_KEY": "env-key",
"FOUNDRY_EMBEDDING_MODEL": "text-model",
"FOUNDRY_IMAGE_EMBEDDING_MODEL": "image-model",
},
),
patch("agent_framework_azure_ai._embedding_client.EmbeddingsClient"),
patch("agent_framework_azure_ai._embedding_client.ImageEmbeddingsClient"),
patch("agent_framework_foundry._embedding_client.EmbeddingsClient"),
patch("agent_framework_foundry._embedding_client.ImageEmbeddingsClient"),
):
client = RawAzureAIInferenceEmbeddingClient()
client = RawFoundryEmbeddingClient()
assert client.model == "text-model"
assert client.image_model == "image-model"
def test_image_model_explicit(self, mock_text_client: AsyncMock, mock_image_client: AsyncMock) -> None:
"""image_model can be set explicitly."""
client = RawAzureAIInferenceEmbeddingClient(
client = RawFoundryEmbeddingClient(
model="text-model",
image_model="image-model",
endpoint="https://test.inference.ai.azure.com",
@@ -242,7 +242,7 @@ class TestRawAzureAIInferenceEmbeddingClient:
self, mock_text_client: AsyncMock, mock_image_client: AsyncMock
) -> None:
"""image_model is passed to the image client embed call."""
client = RawAzureAIInferenceEmbeddingClient(
client = RawFoundryEmbeddingClient(
model="text-model",
image_model="image-model",
endpoint="https://test.inference.ai.azure.com",
@@ -256,12 +256,10 @@ class TestRawAzureAIInferenceEmbeddingClient:
assert call_kwargs.kwargs["model"] == "image-model"
class TestAzureAIInferenceEmbeddingClient:
"""Tests for the telemetry-enabled Azure AI Inference embedding client."""
class TestFoundryEmbeddingClient:
"""Tests for the telemetry-enabled Foundry embedding client."""
async def test_text_embeddings(
self, client: AzureAIInferenceEmbeddingClient[Any], mock_text_client: AsyncMock
) -> None:
async def test_text_embeddings(self, client: FoundryEmbeddingClient[Any], mock_text_client: AsyncMock) -> None:
"""Text embeddings work through the telemetry layer."""
result = await client.get_embeddings(["hello"])
assert len(result) == 1
@@ -269,11 +267,11 @@ class TestAzureAIInferenceEmbeddingClient:
async def test_otel_provider_name_default(self) -> None:
"""Default OTEL provider name is azure.ai.inference."""
assert AzureAIInferenceEmbeddingClient.OTEL_PROVIDER_NAME == "azure.ai.inference"
assert FoundryEmbeddingClient.OTEL_PROVIDER_NAME == "azure.ai.inference"
async def test_otel_provider_name_override(self, mock_text_client: AsyncMock, mock_image_client: AsyncMock) -> None:
"""OTEL provider name can be overridden."""
client = AzureAIInferenceEmbeddingClient(
client = FoundryEmbeddingClient(
model="test-model",
endpoint="https://test.inference.ai.azure.com",
api_key="test-key",
@@ -284,32 +282,32 @@ class TestAzureAIInferenceEmbeddingClient:
assert client.otel_provider_name == "custom-provider"
_SKIP_REASON = "Azure AI Inference integration tests disabled"
_SKIP_REASON = "Foundry inference integration tests disabled"
def _integration_tests_enabled() -> bool:
def _foundry_integration_tests_enabled() -> bool:
return bool(
os.environ.get("AZURE_AI_INFERENCE_ENDPOINT")
and os.environ.get("AZURE_AI_INFERENCE_API_KEY")
and os.environ.get("AZURE_AI_INFERENCE_EMBEDDING_MODEL")
os.environ.get("FOUNDRY_MODELS_ENDPOINT")
and os.environ.get("FOUNDRY_MODELS_API_KEY")
and os.environ.get("FOUNDRY_EMBEDDING_MODEL")
)
skip_if_azure_ai_inference_integration_tests_disabled = pytest.mark.skipif(
not _integration_tests_enabled(),
skip_if_foundry_inference_integration_tests_disabled = pytest.mark.skipif(
not _foundry_integration_tests_enabled(),
reason=_SKIP_REASON,
)
class TestAzureAIInferenceEmbeddingIntegration:
"""Integration tests requiring a live Azure AI Inference endpoint."""
class TestFoundryEmbeddingIntegration:
"""Integration tests requiring a live Foundry inference endpoint."""
@pytest.mark.flaky
@pytest.mark.integration
@skip_if_azure_ai_inference_integration_tests_disabled
@skip_if_foundry_inference_integration_tests_disabled
async def test_text_embedding_live(self) -> None:
"""Generate text embeddings against a live endpoint."""
client = AzureAIInferenceEmbeddingClient()
client = FoundryEmbeddingClient()
result = await client.get_embeddings(["Hello, world!"])
assert len(result) == 1
assert len(result[0].vector) > 0
@@ -7,7 +7,7 @@ configured for GAIA benchmark tasks using the OpenAI Responses API.
Required Environment Variables:
OPENAI_API_KEY: Your OpenAI API key
OPENAI_RESPONSES_MODEL: Model to use with Responses API (e.g., gpt-4o, gpt-4o-mini)
OPENAI_CHAT_MODEL: Model to use with Responses API (e.g., gpt-4o, gpt-4o-mini)
Optional Environment Variables:
OPENAI_BASE_URL: Custom API base URL if using a proxy or compatible service
@@ -19,7 +19,7 @@ Authentication:
Example:
export OPENAI_API_KEY="sk-..."
export OPENAI_RESPONSES_MODEL="gpt-4o"
export OPENAI_CHAT_MODEL="gpt-4o"
"""
from collections.abc import AsyncIterator
+15 -8
View File
@@ -36,16 +36,20 @@ These variables are used when the client is configured for OpenAI:
| `OPENAI_ORG_ID` | OpenAI organization ID |
| `OPENAI_BASE_URL` | Custom OpenAI-compatible base URL |
| `OPENAI_MODEL` | Generic fallback model |
| `OPENAI_RESPONSES_MODEL` | Preferred model for `OpenAIChatClient` |
| `OPENAI_CHAT_MODEL` | Preferred model for `OpenAIChatCompletionClient` |
| `OPENAI_CHAT_MODEL` | Preferred model for `OpenAIChatClient` |
| `OPENAI_CHAT_COMPLETION_MODEL` | Preferred model for `OpenAIChatCompletionClient` |
| `OPENAI_EMBEDDING_MODEL` | Preferred model for `OpenAIEmbeddingClient` |
Model lookup order:
- `OpenAIChatClient`: `OPENAI_RESPONSES_MODEL` -> `OPENAI_MODEL`
- `OpenAIChatCompletionClient`: `OPENAI_CHAT_MODEL` -> `OPENAI_MODEL`
- `OpenAIChatClient`: `OPENAI_CHAT_MODEL` -> `OPENAI_MODEL`
- `OpenAIChatCompletionClient`: `OPENAI_CHAT_COMPLETION_MODEL` -> `OPENAI_MODEL`
- `OpenAIEmbeddingClient`: `OPENAI_EMBEDDING_MODEL` -> `OPENAI_MODEL`
These model variables are only consulted when you do not pass `model=` directly. In other words,
`OpenAIChatClient(model="...")` ignores `OPENAI_CHAT_MODEL`, and
`OpenAIChatCompletionClient(model="...")` ignores `OPENAI_CHAT_COMPLETION_MODEL`.
### Azure OpenAI
These variables are used when the client is configured for Azure OpenAI:
@@ -57,16 +61,19 @@ These variables are used when the client is configured for Azure OpenAI:
| `AZURE_OPENAI_API_KEY` | Azure OpenAI API key |
| `AZURE_OPENAI_API_VERSION` | Azure OpenAI API version |
| `AZURE_OPENAI_MODEL` | Generic fallback deployment |
| `AZURE_OPENAI_RESPONSES_MODEL` | Preferred deployment for `OpenAIChatClient` |
| `AZURE_OPENAI_CHAT_MODEL` | Preferred deployment for `OpenAIChatCompletionClient` |
| `AZURE_OPENAI_CHAT_MODEL` | Preferred deployment for `OpenAIChatClient` |
| `AZURE_OPENAI_CHAT_COMPLETION_MODEL` | Preferred deployment for `OpenAIChatCompletionClient` |
| `AZURE_OPENAI_EMBEDDING_MODEL` | Preferred deployment for `OpenAIEmbeddingClient` |
Deployment lookup order:
- `OpenAIChatClient`: `AZURE_OPENAI_RESPONSES_MODEL` -> `AZURE_OPENAI_MODEL`
- `OpenAIChatCompletionClient`: `AZURE_OPENAI_CHAT_MODEL` -> `AZURE_OPENAI_MODEL`
- `OpenAIChatClient`: `AZURE_OPENAI_CHAT_MODEL` -> `AZURE_OPENAI_MODEL`
- `OpenAIChatCompletionClient`: `AZURE_OPENAI_CHAT_COMPLETION_MODEL` -> `AZURE_OPENAI_MODEL`
- `OpenAIEmbeddingClient`: `AZURE_OPENAI_EMBEDDING_MODEL` -> `AZURE_OPENAI_MODEL`
For Azure routing, the same rule applies: the client-specific deployment variable is checked first,
then the generic `AZURE_OPENAI_MODEL` fallback. Passing `model=` overrides both environment variables.
When both OpenAI and Azure environment variables are present, the generic clients prefer OpenAI
when `OPENAI_API_KEY` is configured. To use Azure explicitly, pass `azure_endpoint` or
`credential`.
@@ -289,7 +289,7 @@ class RawOpenAIChatClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``OPENAI_RESPONSES_MODEL`` and then ``OPENAI_MODEL``.
reads ``OPENAI_CHAT_MODEL`` and then ``OPENAI_MODEL``.
api_key: API key. When not provided explicitly, the constructor reads
``OPENAI_API_KEY``. A callable API key is also supported.
org_id: OpenAI organization ID. When not provided explicitly, the constructor reads
@@ -331,7 +331,7 @@ class RawOpenAIChatClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``AZURE_OPENAI_RESPONSES_MODEL`` and then
reads ``AZURE_OPENAI_CHAT_MODEL`` and then
``AZURE_OPENAI_MODEL``.
azure_endpoint: Azure resource endpoint. When not provided explicitly, the constructor
reads ``AZURE_OPENAI_ENDPOINT``.
@@ -380,8 +380,8 @@ class RawOpenAIChatClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``OPENAI_RESPONSES_MODEL`` and then ``OPENAI_MODEL`` for OpenAI,
or ``AZURE_OPENAI_RESPONSES_MODEL`` and then ``AZURE_OPENAI_MODEL`` for Azure.
reads ``OPENAI_CHAT_MODEL`` and then ``OPENAI_MODEL`` for OpenAI,
or ``AZURE_OPENAI_CHAT_MODEL`` and then ``AZURE_OPENAI_MODEL`` for Azure.
api_key: API key override. For OpenAI this maps to ``OPENAI_API_KEY``.
For Azure this can be used instead of ``AZURE_OPENAI_API_KEY`` for key
auth. A callable token provider is also accepted for backwards compatibility,
@@ -418,10 +418,10 @@ class RawOpenAIChatClient( # type: ignore[misc]
2. Explicit OpenAI API key or ``OPENAI_API_KEY``
3. Azure environment fallback
OpenAI routing reads ``OPENAI_API_KEY``, ``OPENAI_RESPONSES_MODEL``,
OpenAI routing reads ``OPENAI_API_KEY``, ``OPENAI_CHAT_MODEL``,
``OPENAI_MODEL``, ``OPENAI_ORG_ID``, and ``OPENAI_BASE_URL``. Azure routing
reads ``AZURE_OPENAI_ENDPOINT``, ``AZURE_OPENAI_BASE_URL``,
``AZURE_OPENAI_API_KEY``, ``AZURE_OPENAI_RESPONSES_MODEL``,
``AZURE_OPENAI_API_KEY``, ``AZURE_OPENAI_CHAT_MODEL``,
``AZURE_OPENAI_MODEL``, and ``AZURE_OPENAI_API_VERSION``.
"""
settings, client, use_azure_client = load_openai_service_settings(
@@ -437,8 +437,8 @@ class RawOpenAIChatClient( # type: ignore[misc]
client=async_client,
env_file_path=env_file_path,
env_file_encoding=env_file_encoding,
openai_model_fields=("responses_model", "model"),
azure_model_fields=("responses_model", "model"),
openai_model_fields=("chat_model", "model"),
azure_model_fields=("chat_model", "model"),
responses_mode=True,
)
@@ -2501,7 +2501,7 @@ class OpenAIChatClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``OPENAI_RESPONSES_MODEL`` and then ``OPENAI_MODEL``.
reads ``OPENAI_CHAT_MODEL`` and then ``OPENAI_MODEL``.
api_key: API key. When not provided explicitly, the constructor reads
``OPENAI_API_KEY``. A callable API key is also supported.
org_id: OpenAI organization ID. When not provided explicitly, the constructor reads
@@ -2547,7 +2547,7 @@ class OpenAIChatClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``AZURE_OPENAI_RESPONSES_MODEL`` and then
reads ``AZURE_OPENAI_CHAT_MODEL`` and then
``AZURE_OPENAI_MODEL``.
azure_endpoint: Azure resource endpoint. When not provided explicitly, the constructor
reads ``AZURE_OPENAI_ENDPOINT``.
@@ -2600,8 +2600,8 @@ class OpenAIChatClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``OPENAI_RESPONSES_MODEL`` and then ``OPENAI_MODEL`` for OpenAI
routing, or ``AZURE_OPENAI_RESPONSES_MODEL`` and then
reads ``OPENAI_CHAT_MODEL`` and then ``OPENAI_MODEL`` for OpenAI
routing, or ``AZURE_OPENAI_CHAT_MODEL`` and then
``AZURE_OPENAI_MODEL`` for Azure routing.
api_key: API key override. For OpenAI routing this maps to ``OPENAI_API_KEY``.
For Azure routing this can be used instead of ``AZURE_OPENAI_API_KEY`` for key
@@ -2641,10 +2641,10 @@ class OpenAIChatClient( # type: ignore[misc]
2. Explicit OpenAI API key or ``OPENAI_API_KEY``
3. Azure environment fallback
OpenAI routing reads ``OPENAI_API_KEY``, ``OPENAI_RESPONSES_MODEL``,
OpenAI routing reads ``OPENAI_API_KEY``, ``OPENAI_CHAT_MODEL``,
``OPENAI_MODEL``, ``OPENAI_ORG_ID``, and ``OPENAI_BASE_URL``. Azure routing
reads ``AZURE_OPENAI_ENDPOINT``, ``AZURE_OPENAI_BASE_URL``,
``AZURE_OPENAI_API_KEY``, ``AZURE_OPENAI_RESPONSES_MODEL``,
``AZURE_OPENAI_API_KEY``, ``AZURE_OPENAI_CHAT_MODEL``,
``AZURE_OPENAI_MODEL``, and ``AZURE_OPENAI_API_VERSION``.
Examples:
@@ -203,7 +203,7 @@ class RawOpenAIChatCompletionClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``OPENAI_CHAT_MODEL`` and then ``OPENAI_MODEL``.
reads ``OPENAI_CHAT_COMPLETION_MODEL`` and then ``OPENAI_MODEL``.
api_key: API key. When not provided explicitly, the constructor reads
``OPENAI_API_KEY``. A callable API key is also supported.
org_id: OpenAI organization ID. When not provided explicitly, the constructor reads
@@ -245,7 +245,7 @@ class RawOpenAIChatCompletionClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``AZURE_OPENAI_CHAT_MODEL`` and then
reads ``AZURE_OPENAI_CHAT_COMPLETION_MODEL`` and then
``AZURE_OPENAI_MODEL``.
azure_endpoint: Azure resource endpoint. When not provided explicitly, the constructor
reads ``AZURE_OPENAI_ENDPOINT``.
@@ -294,8 +294,8 @@ class RawOpenAIChatCompletionClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``OPENAI_CHAT_MODEL`` and then ``OPENAI_MODEL`` for OpenAI routing,
or ``AZURE_OPENAI_CHAT_MODEL`` and then ``AZURE_OPENAI_MODEL`` for Azure routing.
reads ``OPENAI_CHAT_COMPLETION_MODEL`` and then ``OPENAI_MODEL`` for OpenAI routing,
or ``AZURE_OPENAI_CHAT_COMPLETION_MODEL`` and then ``AZURE_OPENAI_MODEL`` for Azure routing.
api_key: API key override. For OpenAI routing this maps to ``OPENAI_API_KEY``.
For Azure routing this can be used instead of ``AZURE_OPENAI_API_KEY`` for key
auth. A callable token provider is also accepted for backwards compatibility,
@@ -332,10 +332,10 @@ class RawOpenAIChatCompletionClient( # type: ignore[misc]
2. Explicit OpenAI API key or ``OPENAI_API_KEY``
3. Azure environment fallback
OpenAI routing reads ``OPENAI_API_KEY``, ``OPENAI_CHAT_MODEL``,
OpenAI routing reads ``OPENAI_API_KEY``, ``OPENAI_CHAT_COMPLETION_MODEL``,
``OPENAI_MODEL``, ``OPENAI_ORG_ID``, and ``OPENAI_BASE_URL``. Azure routing
reads ``AZURE_OPENAI_ENDPOINT``, ``AZURE_OPENAI_BASE_URL``,
``AZURE_OPENAI_API_KEY``, ``AZURE_OPENAI_CHAT_MODEL``,
``AZURE_OPENAI_API_KEY``, ``AZURE_OPENAI_CHAT_COMPLETION_MODEL``,
``AZURE_OPENAI_MODEL``, and ``AZURE_OPENAI_API_VERSION``.
"""
settings, client, use_azure_client = load_openai_service_settings(
@@ -351,8 +351,8 @@ class RawOpenAIChatCompletionClient( # type: ignore[misc]
client=async_client,
env_file_path=env_file_path,
env_file_encoding=env_file_encoding,
openai_model_fields=("chat_model", "model"),
azure_model_fields=("chat_model", "model"),
openai_model_fields=("chat_completion_model", "model"),
azure_model_fields=("chat_completion_model", "model"),
)
self.client = client
@@ -1048,7 +1048,7 @@ class OpenAIChatCompletionClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``OPENAI_CHAT_MODEL`` and then ``OPENAI_MODEL``.
reads ``OPENAI_CHAT_COMPLETION_MODEL`` and then ``OPENAI_MODEL``.
api_key: API key. When not provided explicitly, the constructor reads
``OPENAI_API_KEY``. A callable API key is also supported.
org_id: OpenAI organization ID. When not provided explicitly, the constructor reads
@@ -1088,7 +1088,7 @@ class OpenAIChatCompletionClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``AZURE_OPENAI_CHAT_MODEL`` and then
reads ``AZURE_OPENAI_CHAT_COMPLETION_MODEL`` and then
``AZURE_OPENAI_MODEL``.
azure_endpoint: Azure resource endpoint. When not provided explicitly, the constructor
reads ``AZURE_OPENAI_ENDPOINT``.
@@ -1135,8 +1135,8 @@ class OpenAIChatCompletionClient( # type: ignore[misc]
Keyword Args:
model: Model identifier to use for the request. When not provided, the constructor
reads ``OPENAI_CHAT_MODEL`` and then ``OPENAI_MODEL`` for OpenAI routing,
or ``AZURE_OPENAI_CHAT_MODEL`` and then
reads ``OPENAI_CHAT_COMPLETION_MODEL`` and then ``OPENAI_MODEL`` for OpenAI routing,
or ``AZURE_OPENAI_CHAT_COMPLETION_MODEL`` and then
``AZURE_OPENAI_MODEL`` for Azure routing.
api_key: API key override. For OpenAI routing this maps to ``OPENAI_API_KEY``.
For Azure routing this can be used instead of ``AZURE_OPENAI_API_KEY`` for key
@@ -1173,10 +1173,10 @@ class OpenAIChatCompletionClient( # type: ignore[misc]
2. Explicit OpenAI API key or ``OPENAI_API_KEY``
3. Azure environment fallback
OpenAI routing reads ``OPENAI_API_KEY``, ``OPENAI_CHAT_MODEL``,
OpenAI routing reads ``OPENAI_API_KEY``, ``OPENAI_CHAT_COMPLETION_MODEL``,
``OPENAI_MODEL``, ``OPENAI_ORG_ID``, and ``OPENAI_BASE_URL``. Azure routing
reads ``AZURE_OPENAI_ENDPOINT``, ``AZURE_OPENAI_BASE_URL``,
``AZURE_OPENAI_API_KEY``, ``AZURE_OPENAI_CHAT_MODEL``,
``AZURE_OPENAI_API_KEY``, ``AZURE_OPENAI_CHAT_COMPLETION_MODEL``,
``AZURE_OPENAI_MODEL``, and ``AZURE_OPENAI_API_VERSION``.
Examples:
@@ -67,10 +67,10 @@ class OpenAISettings(TypedDict, total=False):
Can be set via environment variable OPENAI_MODEL.
embedding_model: The OpenAI embedding model to use, for example, text-embedding-3-small.
Can be set via environment variable OPENAI_EMBEDDING_MODEL.
chat_model: The OpenAI chat-completions model to prefer before OPENAI_MODEL.
chat_model: The OpenAIChatClient model to prefer before OPENAI_MODEL.
Can be set via environment variable OPENAI_CHAT_MODEL.
responses_model: The OpenAI responses model to prefer before OPENAI_MODEL.
Can be set via environment variable OPENAI_RESPONSES_MODEL.
chat_completion_model: The OpenAIChatCompletionClient model to prefer before OPENAI_MODEL.
Can be set via environment variable OPENAI_CHAT_COMPLETION_MODEL.
Examples:
.. code-block:: python
@@ -95,7 +95,7 @@ class OpenAISettings(TypedDict, total=False):
model: str | None
embedding_model: str | None
chat_model: str | None
responses_model: str | None
chat_completion_model: str | None
class AzureOpenAISettings(TypedDict, total=False):
@@ -107,24 +107,24 @@ class AzureOpenAISettings(TypedDict, total=False):
model: str | None
embedding_model: str | None
chat_model: str | None
responses_model: str | None
chat_completion_model: str | None
api_version: str | None
OpenAIModelSettingName = Literal["model", "embedding_model", "chat_model", "responses_model"]
OpenAIModelSettingName = Literal["model", "embedding_model", "chat_model", "chat_completion_model"]
OPENAI_MODEL_ENV_VARS: dict[OpenAIModelSettingName, str] = {
"model": "OPENAI_MODEL",
"embedding_model": "OPENAI_EMBEDDING_MODEL",
"chat_model": "OPENAI_CHAT_MODEL",
"responses_model": "OPENAI_RESPONSES_MODEL",
"chat_completion_model": "OPENAI_CHAT_COMPLETION_MODEL",
}
AZURE_MODEL_ENV_VARS: dict[OpenAIModelSettingName, str] = {
"model": "AZURE_OPENAI_MODEL",
"embedding_model": "AZURE_OPENAI_EMBEDDING_MODEL",
"chat_model": "AZURE_OPENAI_CHAT_MODEL",
"responses_model": "AZURE_OPENAI_RESPONSES_MODEL",
"chat_completion_model": "AZURE_OPENAI_CHAT_COMPLETION_MODEL",
}
@@ -43,15 +43,15 @@ def openai_unit_test_env(monkeypatch, exclude_list, override_env_param_dict): #
"OPENAI_ORG_ID",
"OPENAI_MODEL",
"OPENAI_EMBEDDING_MODEL",
"OPENAI_CHAT_COMPLETION_MODEL",
"OPENAI_CHAT_MODEL",
"OPENAI_RESPONSES_MODEL",
"OPENAI_API_VERSION",
"OPENAI_BASE_URL",
"AZURE_OPENAI_ENDPOINT",
"AZURE_OPENAI_BASE_URL",
"AZURE_OPENAI_API_KEY",
"AZURE_OPENAI_CHAT_COMPLETION_MODEL",
"AZURE_OPENAI_CHAT_MODEL",
"AZURE_OPENAI_RESPONSES_MODEL",
"AZURE_OPENAI_EMBEDDING_MODEL",
"AZURE_OPENAI_MODEL",
"AZURE_OPENAI_API_VERSION",
@@ -92,15 +92,15 @@ def azure_openai_unit_test_env(monkeypatch, exclude_list, override_env_param_dic
"OPENAI_ORG_ID",
"OPENAI_MODEL",
"OPENAI_EMBEDDING_MODEL",
"OPENAI_CHAT_COMPLETION_MODEL",
"OPENAI_CHAT_MODEL",
"OPENAI_RESPONSES_MODEL",
"OPENAI_API_VERSION",
"OPENAI_BASE_URL",
"AZURE_OPENAI_ENDPOINT",
"AZURE_OPENAI_BASE_URL",
"AZURE_OPENAI_API_KEY",
"AZURE_OPENAI_CHAT_COMPLETION_MODEL",
"AZURE_OPENAI_CHAT_MODEL",
"AZURE_OPENAI_RESPONSES_MODEL",
"AZURE_OPENAI_EMBEDDING_MODEL",
"AZURE_OPENAI_MODEL",
"AZURE_OPENAI_API_VERSION",
@@ -109,8 +109,8 @@ def azure_openai_unit_test_env(monkeypatch, exclude_list, override_env_param_dic
env_vars = {
"AZURE_OPENAI_ENDPOINT": "https://test-endpoint.openai.azure.com",
"AZURE_OPENAI_CHAT_MODEL": "test_chat_deployment",
"AZURE_OPENAI_RESPONSES_MODEL": "test_responses_deployment",
"AZURE_OPENAI_CHAT_COMPLETION_MODEL": "test_chat_deployment",
"AZURE_OPENAI_CHAT_MODEL": "test_responses_deployment",
"AZURE_OPENAI_EMBEDDING_MODEL": "test_embedding_deployment",
"AZURE_OPENAI_MODEL": "test_deployment",
"AZURE_OPENAI_API_KEY": "test_api_key",
@@ -150,12 +150,12 @@ def test_openai_chat_client_tool_methods_return_dict() -> None:
assert web_tool.get("type") == "web_search"
def test_init_prefers_openai_responses_model(monkeypatch, openai_unit_test_env: dict[str, str]) -> None:
monkeypatch.setenv("OPENAI_RESPONSES_MODEL", "test_responses_model")
def test_init_prefers_openai_chat_model(monkeypatch, openai_unit_test_env: dict[str, str]) -> None:
monkeypatch.setenv("OPENAI_CHAT_MODEL", "test_chat_model")
openai_responses_client = OpenAIChatClient()
assert openai_responses_client.model == "test_responses_model"
assert openai_responses_client.model == "test_chat_model"
def test_init_validation_fail() -> None:
@@ -23,7 +23,7 @@ pytestmark = pytest.mark.azure
skip_if_azure_openai_integration_tests_disabled = pytest.mark.skipif(
os.getenv("AZURE_OPENAI_ENDPOINT", "") in ("", "https://test-endpoint.openai.azure.com")
or (os.getenv("AZURE_OPENAI_RESPONSES_MODEL", "") == "" and os.getenv("AZURE_OPENAI_MODEL", "") == ""),
or (os.getenv("AZURE_OPENAI_CHAT_MODEL", "") == "" and os.getenv("AZURE_OPENAI_MODEL", "") == ""),
reason="No real Azure OpenAI endpoint or responses deployment provided; skipping integration tests.",
)
@@ -35,7 +35,7 @@ def _with_azure_openai_debug() -> Any:
try:
return await func(*args, **kwargs)
except Exception as exc:
model = os.getenv("AZURE_OPENAI_RESPONSES_MODEL") or os.getenv("AZURE_OPENAI_MODEL", "<unset>")
model = os.getenv("AZURE_OPENAI_CHAT_MODEL") or os.getenv("AZURE_OPENAI_MODEL", "<unset>")
api_version = os.getenv("AZURE_OPENAI_API_VERSION") or "preview"
endpoint = os.getenv("AZURE_OPENAI_ENDPOINT", "<unset>")
debug_message = f"Azure OpenAI debug: endpoint={endpoint}, model={model}, api_version={api_version}"
@@ -96,7 +96,7 @@ async def get_weather(location: str) -> str:
def test_init_with_azure_endpoint(azure_openai_unit_test_env: dict[str, str]) -> None:
client = OpenAIChatClient(credential=AzureCliCredential())
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_RESPONSES_MODEL"]
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_CHAT_MODEL"]
assert isinstance(client, SupportsChatGetResponse)
assert isinstance(client.client, AsyncAzureOpenAI)
assert client.OTEL_PROVIDER_NAME == "azure.ai.openai"
@@ -106,7 +106,7 @@ def test_init_with_azure_endpoint(azure_openai_unit_test_env: dict[str, str]) ->
def test_init_auto_detects_azure_env(azure_openai_unit_test_env: dict[str, str]) -> None:
client = OpenAIChatClient()
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_RESPONSES_MODEL"]
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_CHAT_MODEL"]
assert isinstance(client.client, AsyncAzureOpenAI)
assert client.azure_endpoint == azure_openai_unit_test_env["AZURE_OPENAI_ENDPOINT"]
@@ -141,7 +141,7 @@ def test_explicit_credential_wins_over_openai_api_key(monkeypatch, azure_openai_
client = OpenAIChatClient(credential=lambda: "token")
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_RESPONSES_MODEL"]
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_CHAT_MODEL"]
assert isinstance(client.client, AsyncAzureOpenAI)
assert client.azure_endpoint == azure_openai_unit_test_env["AZURE_OPENAI_ENDPOINT"]
@@ -149,7 +149,7 @@ def test_explicit_credential_wins_over_openai_api_key(monkeypatch, azure_openai_
def test_init_falls_back_to_generic_azure_deployment_env(
monkeypatch, azure_openai_unit_test_env: dict[str, str]
) -> None:
monkeypatch.delenv("AZURE_OPENAI_RESPONSES_MODEL", raising=False)
monkeypatch.delenv("AZURE_OPENAI_CHAT_MODEL", raising=False)
client = OpenAIChatClient()
@@ -160,9 +160,9 @@ def test_init_falls_back_to_generic_azure_deployment_env(
def test_init_does_not_fall_back_to_openai_responses_model_for_azure_env(
monkeypatch, azure_openai_unit_test_env: dict[str, str]
) -> None:
monkeypatch.delenv("AZURE_OPENAI_RESPONSES_MODEL", raising=False)
monkeypatch.delenv("AZURE_OPENAI_CHAT_MODEL", raising=False)
monkeypatch.delenv("AZURE_OPENAI_MODEL", raising=False)
monkeypatch.setenv("OPENAI_RESPONSES_MODEL", "test_responses_model")
monkeypatch.setenv("OPENAI_CHAT_MODEL", "test_responses_model")
with pytest.raises(SettingNotFoundError, match="Azure OpenAI client requires a model"):
OpenAIChatClient()
@@ -171,9 +171,9 @@ def test_init_does_not_fall_back_to_openai_responses_model_for_azure_env(
def test_init_does_not_fall_back_to_openai_model_for_azure_env(
monkeypatch, azure_openai_unit_test_env: dict[str, str]
) -> None:
monkeypatch.delenv("AZURE_OPENAI_RESPONSES_MODEL", raising=False)
monkeypatch.delenv("AZURE_OPENAI_CHAT_MODEL", raising=False)
monkeypatch.delenv("AZURE_OPENAI_MODEL", raising=False)
monkeypatch.delenv("OPENAI_RESPONSES_MODEL", raising=False)
monkeypatch.delenv("OPENAI_CHAT_MODEL", raising=False)
monkeypatch.setenv("OPENAI_MODEL", "gpt-5")
with pytest.raises(SettingNotFoundError, match="Azure OpenAI client requires a model"):
@@ -203,7 +203,7 @@ def test_init_with_credential_wraps_async_token_credential(
def test_init_uses_default_azure_api_version(azure_openai_unit_test_env: dict[str, str]) -> None:
client = OpenAIChatClient(credential=AzureCliCredential())
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_RESPONSES_MODEL"]
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_CHAT_MODEL"]
assert client.api_version is not None
@@ -79,7 +79,7 @@ def test_supports_web_search_only() -> None:
def test_init_prefers_openai_chat_model(monkeypatch, openai_unit_test_env: dict[str, str]) -> None:
monkeypatch.setenv("OPENAI_CHAT_MODEL", "test_chat_model")
monkeypatch.setenv("OPENAI_CHAT_COMPLETION_MODEL", "test_chat_model")
open_ai_chat_completion = OpenAIChatCompletionClient()
@@ -29,7 +29,7 @@ pytestmark = pytest.mark.azure
skip_if_azure_openai_integration_tests_disabled = pytest.mark.skipif(
os.getenv("AZURE_OPENAI_ENDPOINT", "") in ("", "https://test-endpoint.openai.azure.com")
or (os.getenv("AZURE_OPENAI_CHAT_MODEL", "") == "" and os.getenv("AZURE_OPENAI_MODEL", "") == ""),
or (os.getenv("AZURE_OPENAI_CHAT_COMPLETION_MODEL", "") == "" and os.getenv("AZURE_OPENAI_MODEL", "") == ""),
reason="No real Azure OpenAI endpoint or chat deployment provided; skipping integration tests.",
)
@@ -41,7 +41,7 @@ def _with_azure_openai_debug() -> Any:
try:
return await func(*args, **kwargs)
except Exception as exc:
model = os.getenv("AZURE_OPENAI_CHAT_MODEL") or os.getenv("AZURE_OPENAI_MODEL", "<unset>")
model = os.getenv("AZURE_OPENAI_CHAT_COMPLETION_MODEL") or os.getenv("AZURE_OPENAI_MODEL", "<unset>")
api_version = os.getenv("AZURE_OPENAI_API_VERSION", "<unset>")
endpoint = os.getenv("AZURE_OPENAI_ENDPOINT", "<unset>")
debug_message = f"Azure OpenAI debug: endpoint={endpoint}, model={model}, api_version={api_version}"
@@ -78,7 +78,7 @@ async def get_weather(location: str) -> str:
def test_init_with_azure_endpoint(azure_openai_unit_test_env: dict[str, str]) -> None:
client = OpenAIChatCompletionClient(azure_endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"))
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_CHAT_MODEL"]
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_CHAT_COMPLETION_MODEL"]
assert isinstance(client, SupportsChatGetResponse)
assert isinstance(client.client, AsyncAzureOpenAI)
assert client.OTEL_PROVIDER_NAME == "azure.ai.openai"
@@ -89,7 +89,7 @@ def test_init_with_azure_endpoint(azure_openai_unit_test_env: dict[str, str]) ->
def test_init_auto_detects_azure_env(azure_openai_unit_test_env: dict[str, str]) -> None:
client = OpenAIChatCompletionClient()
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_CHAT_MODEL"]
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_CHAT_COMPLETION_MODEL"]
assert isinstance(client.client, AsyncAzureOpenAI)
assert client.azure_endpoint == azure_openai_unit_test_env["AZURE_OPENAI_ENDPOINT"]
@@ -111,7 +111,7 @@ def test_explicit_credential_wins_over_openai_api_key(monkeypatch, azure_openai_
client = OpenAIChatCompletionClient(credential=lambda: "token")
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_CHAT_MODEL"]
assert client.model == azure_openai_unit_test_env["AZURE_OPENAI_CHAT_COMPLETION_MODEL"]
assert isinstance(client.client, AsyncAzureOpenAI)
assert client.azure_endpoint == azure_openai_unit_test_env["AZURE_OPENAI_ENDPOINT"]
@@ -119,7 +119,7 @@ def test_explicit_credential_wins_over_openai_api_key(monkeypatch, azure_openai_
def test_init_falls_back_to_generic_azure_deployment_env(
monkeypatch, azure_openai_unit_test_env: dict[str, str]
) -> None:
monkeypatch.delenv("AZURE_OPENAI_CHAT_MODEL", raising=False)
monkeypatch.delenv("AZURE_OPENAI_CHAT_COMPLETION_MODEL", raising=False)
client = OpenAIChatCompletionClient()
@@ -130,9 +130,9 @@ def test_init_falls_back_to_generic_azure_deployment_env(
def test_init_does_not_fall_back_to_openai_chat_model_for_azure_env(
monkeypatch, azure_openai_unit_test_env: dict[str, str]
) -> None:
monkeypatch.delenv("AZURE_OPENAI_CHAT_MODEL", raising=False)
monkeypatch.delenv("AZURE_OPENAI_CHAT_COMPLETION_MODEL", raising=False)
monkeypatch.delenv("AZURE_OPENAI_MODEL", raising=False)
monkeypatch.setenv("OPENAI_CHAT_MODEL", "test_chat_model")
monkeypatch.setenv("OPENAI_CHAT_COMPLETION_MODEL", "test_chat_model")
with pytest.raises(SettingNotFoundError, match="Azure OpenAI client requires a model"):
OpenAIChatCompletionClient()
@@ -141,9 +141,9 @@ def test_init_does_not_fall_back_to_openai_chat_model_for_azure_env(
def test_init_does_not_fall_back_to_openai_model_for_azure_env(
monkeypatch, azure_openai_unit_test_env: dict[str, str]
) -> None:
monkeypatch.delenv("AZURE_OPENAI_CHAT_MODEL", raising=False)
monkeypatch.delenv("AZURE_OPENAI_CHAT_COMPLETION_MODEL", raising=False)
monkeypatch.delenv("AZURE_OPENAI_MODEL", raising=False)
monkeypatch.delenv("OPENAI_CHAT_MODEL", raising=False)
monkeypatch.delenv("OPENAI_CHAT_COMPLETION_MODEL", raising=False)
monkeypatch.setenv("OPENAI_MODEL", "gpt-5")
with pytest.raises(SettingNotFoundError, match="Azure OpenAI client requires a model"):
-2
View File
@@ -70,7 +70,6 @@ agent-framework-ag-ui = { workspace = true }
agent-framework-azure-ai-search = { workspace = true }
agent-framework-azure-cosmos = { workspace = true }
agent-framework-anthropic = { workspace = true }
agent-framework-azure-ai = { workspace = true }
agent-framework-azurefunctions = { workspace = true }
agent-framework-bedrock = { workspace = true }
agent-framework-chatkit = { workspace = true }
@@ -187,7 +186,6 @@ executionEnvironments = [
{ root = "packages/ag-ui/tests", reportPrivateUsage = "none" },
{ root = "packages/anthropic/tests", reportPrivateUsage = "none" },
{ root = "packages/azure-ai-search/tests", reportPrivateUsage = "none" },
{ root = "packages/azure-ai/tests", reportPrivateUsage = "none" },
{ root = "packages/azure-cosmos/tests", reportPrivateUsage = "none" },
{ root = "packages/azurefunctions/tests", reportPrivateUsage = "none" },
{ root = "packages/bedrock/tests", reportPrivateUsage = "none" },
@@ -61,8 +61,8 @@ Depending on the selected client, set the appropriate environment variables:
**For OpenAI clients:**
- `OPENAI_API_KEY`: Your OpenAI API key
- `OPENAI_CHAT_MODEL`: The OpenAI model for `openai_chat_completion`
- `OPENAI_RESPONSES_MODEL`: The OpenAI model for `openai_responses`
- `OPENAI_CHAT_COMPLETION_MODEL`: The OpenAI model for `openai_chat_completion`
- `OPENAI_CHAT_MODEL`: The OpenAI model for `openai_responses`
**For Anthropic client (`anthropic`):**
- `ANTHROPIC_API_KEY`: Your Anthropic API key
@@ -8,6 +8,7 @@ These samples demonstrate different approaches to managing conversation history
|------|-------------|
| [`suspend_resume_session.py`](suspend_resume_session.py) | Suspend and resume conversation sessions, comparing service-managed sessions (Azure AI Foundry) with in-memory sessions (OpenAI). |
| [`custom_history_provider.py`](custom_history_provider.py) | Implement a custom history provider by extending `BaseHistoryProvider`, enabling conversation persistence in your preferred storage backend. |
| [`cosmos_history_provider.py`](cosmos_history_provider.py) | Use Azure Cosmos DB as a history provider for durable conversation storage with `CosmosHistoryProvider`. |
| [`redis_history_provider.py`](redis_history_provider.py) | Use Redis as a history provider for persistent conversation history storage across sessions. |
## Prerequisites
@@ -21,6 +22,14 @@ These samples demonstrate different approaches to managing conversation history
**For `custom_history_provider.py`:**
- `OPENAI_API_KEY`: Your OpenAI API key
**For `cosmos_history_provider.py`:**
- `FOUNDRY_PROJECT_ENDPOINT`: Your Azure AI Foundry project endpoint
- `FOUNDRY_MODEL`: The Foundry model deployment name
- `AZURE_COSMOS_ENDPOINT`: Your Azure Cosmos DB account endpoint
- `AZURE_COSMOS_DATABASE_NAME`: The database that stores conversation history
- `AZURE_COSMOS_CONTAINER_NAME`: The container that stores conversation history
- Either `AZURE_COSMOS_KEY` or Azure CLI authentication (`az login`)
**For `redis_history_provider.py`:**
- `OPENAI_API_KEY`: Your OpenAI API key
- A running Redis server — default URL is `redis://localhost:6379`
@@ -1,20 +1,19 @@
# Copyright (c) Microsoft. All rights reserved.
# ruff: noqa: T201
import asyncio
import os
from agent_framework import Agent
from agent_framework.azure import CosmosHistoryProvider
from agent_framework.foundry import FoundryChatClient
from azure.identity.aio import AzureCliCredential
from dotenv import load_dotenv
from agent_framework_azure_cosmos import CosmosHistoryProvider
# Load environment variables from .env file.
load_dotenv()
"""
This sample demonstrates CosmosHistoryProvider as an agent context provider.
This sample demonstrates CosmosHistoryProvider as an agent history provider.
Key components:
- FoundryChatClient configured with an Azure AI project endpoint
@@ -54,39 +53,38 @@ async def main() -> None:
)
return
# 1. Create an Azure credential and Foundry chat client using project endpoint auth.
async with AzureCliCredential() as credential:
client = FoundryChatClient(
project_endpoint=project_endpoint,
model=model,
credential=credential,
)
# 1. Create an Azure credential and a CosmosHistoryProvider for agent context
async with (
AzureCliCredential() as credential,
CosmosHistoryProvider(
endpoint=cosmos_endpoint,
database_name=cosmos_database_name,
container_name=cosmos_container_name,
credential=cosmos_key or credential,
) as history_provider,
# 2. Create an agent that uses Cosmos for persisted conversation history.
Agent(
client=FoundryChatClient(
project_endpoint=project_endpoint,
model=model,
credential=credential,
),
name="CosmosHistoryAgent",
instructions="You are a helpful assistant that remembers prior turns.",
context_providers=[history_provider],
default_options={"store": False},
) as agent,
):
# 3. Create a session (session_id is used as the partition key).
session = agent.create_session()
# 2. Create an agent that uses the history provider as a context provider.
async with (
CosmosHistoryProvider(
endpoint=cosmos_endpoint,
database_name=cosmos_database_name,
container_name=cosmos_container_name,
credential=cosmos_key or credential,
) as history_provider,
client.as_agent(
name="CosmosHistoryAgent",
instructions="You are a helpful assistant that remembers prior turns.",
context_providers=[history_provider],
default_options={"store": False},
) as agent,
):
# 3. Create a session (session_id is used as the partition key).
session = agent.create_session()
# 4. Run a multi-turn conversation; history is persisted by CosmosHistoryProvider.
response1 = await agent.run("My name is Ada and I enjoy distributed systems.", session=session)
print(f"Assistant: {response1.text}")
# 4. Run a multi-turn conversation; history is persisted by CosmosHistoryProvider.
response1 = await agent.run("My name is Ada and I enjoy distributed systems.", session=session)
print(f"Assistant: {response1.text}")
response2 = await agent.run("What do you remember about me?", session=session)
print(f"Assistant: {response2.text}")
print(f"Container: {history_provider.container_name}")
response2 = await agent.run("What do you remember about me?", session=session)
print(f"Assistant: {response2.text}")
print(f"Container: {history_provider.container_name}")
if __name__ == "__main__":
+1 -1
View File
@@ -8,7 +8,7 @@ FOUNDRY_MODEL=gpt-4o
# Azure OpenAI workflow sample
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
AZURE_OPENAI_RESPONSES_MODEL=gpt-4o
AZURE_OPENAI_CHAT_MODEL=gpt-4o
# Optional fallback env name also supported by workflow_with_agents/workflow.py:
AZURE_OPENAI_MODEL=gpt-4o
# Optional if you need to override the default API version:
+2 -2
View File
@@ -94,7 +94,7 @@ workflow_name/
| Sample | What it demonstrates | Required keys / auth |
| ------ | -------------------- | -------------------- |
| [**workflow_declarative/**](workflow_declarative/) | A YAML-defined workflow loaded through `WorkflowFactory`, with nested age-based branching and no model client code. | None |
| [**workflow_with_agents/**](workflow_with_agents/) | A content review workflow that uses agents as executors and routes based on structured review output (`Writer -> Reviewer -> Editor/Publisher -> Summarizer`). | `AZURE_OPENAI_ENDPOINT`, plus `AZURE_OPENAI_RESPONSES_MODEL` or `AZURE_OPENAI_MODEL`; Azure CLI auth via `az login`; `AZURE_OPENAI_API_VERSION` is optional |
| [**workflow_with_agents/**](workflow_with_agents/) | A content review workflow that uses agents as executors and routes based on structured review output (`Writer -> Reviewer -> Editor/Publisher -> Summarizer`). | `AZURE_OPENAI_ENDPOINT`, plus `AZURE_OPENAI_CHAT_MODEL` or `AZURE_OPENAI_MODEL`; Azure CLI auth via `az login`; `AZURE_OPENAI_API_VERSION` is optional |
| [**workflow_spam/**](workflow_spam/) | A multi-step spam detection workflow with human-in-the-loop approval, branching for spam vs. legitimate messages, and a final reporting step. | None |
| [**workflow_fanout/**](workflow_fanout/) | A larger fan-out/fan-in data processing workflow with parallel validation, multiple transformations, QA, aggregation, and demo failure toggles. | None |
@@ -130,7 +130,7 @@ export FOUNDRY_MODEL="gpt-4o"
# Azure OpenAI workflow_with_agents sample
export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com"
export AZURE_OPENAI_RESPONSES_MODEL="gpt-4o"
export AZURE_OPENAI_CHAT_MODEL="gpt-4o"
export AZURE_OPENAI_MODEL="gpt-4o"
az login
@@ -2,7 +2,7 @@
# This sample uses Azure CLI auth, so run `az login` before starting DevUI.
AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
AZURE_OPENAI_RESPONSES_MODEL=gpt-4o
AZURE_OPENAI_CHAT_MODEL=gpt-4o
# Optional fallback env name also supported by the client:
# AZURE_OPENAI_MODEL=gpt-4o
# Optional if you need to override the default API version:
@@ -65,7 +65,7 @@ def is_approved(message: Any) -> bool:
# Create Azure OpenAI Responses chat client
client = OpenAIChatClient(
model=os.environ.get("AZURE_OPENAI_RESPONSES_MODEL") or os.environ.get("AZURE_OPENAI_MODEL"),
model=os.environ.get("AZURE_OPENAI_CHAT_MODEL") or os.environ.get("AZURE_OPENAI_MODEL"),
azure_endpoint=os.environ.get("AZURE_OPENAI_ENDPOINT"),
api_version=os.environ.get("AZURE_OPENAI_API_VERSION"),
credential=AzureCliCredential(),
@@ -1,10 +1,10 @@
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "agent-framework-azure-ai",
# "agent-framework-foundry",
# ]
# ///
# Run with: uv run samples/02-agents/embeddings/azure_ai_inference_embeddings.py
# Run with: uv run samples/02-agents/embeddings/foundry_embeddings.py
# Copyright (c) Microsoft. All rights reserved.
@@ -12,28 +12,29 @@ import asyncio
import pathlib
from agent_framework import Content
from agent_framework.azure import AzureAIInferenceEmbeddingClient
from agent_framework.foundry import FoundryEmbeddingClient
from dotenv import load_dotenv
load_dotenv()
"""Azure AI Inference Image Embedding Example
"""Microsoft Foundry Image Embedding Example
This sample demonstrates how to generate image embeddings using the
Azure AI Inference embedding client with the Cohere-embed-v3-english model.
Foundry embedding client with the Cohere-embed-v3-english model.
Images are passed as ``Content`` objects created with ``Content.from_data()``.
Prerequisites:
Deploy an embedding model in Azure AI Inference that supports image inputs, such as Cohere-embed-v3-english.
Deploy an embedding model to a Foundry-hosted inference endpoint that supports image inputs,
such as Cohere-embed-v3-english.
The details page for that model, has a target URI and a Key, which should be set in environment variables or a .env
file as follows, the target URI should append the `/models` path:
- AZURE_AI_INFERENCE_ENDPOINT: Your Azure AI model inference endpoint URL, for instance:
- FOUNDRY_MODELS_ENDPOINT: Your Foundry models endpoint URL, for instance:
https://<apim-instance>.azure-api.net/<foundry-instance>/models
- AZURE_AI_INFERENCE_API_KEY: Your API key
- AZURE_AI_INFERENCE_EMBEDDING_MODEL: The text embedding model name
- FOUNDRY_MODELS_API_KEY: Your API key
- FOUNDRY_EMBEDDING_MODEL: The text embedding model name
(e.g. "text-embedding-3-small")
- AZURE_AI_INFERENCE_IMAGE_EMBEDDING_MODEL: The image embedding model name
- FOUNDRY_IMAGE_EMBEDDING_MODEL: The image embedding model name
(e.g. "Cohere-embed-v3-english")
"""
@@ -41,8 +42,8 @@ SAMPLE_IMAGE_PATH = pathlib.Path(__file__).parent.parent.parent / "shared" / "sa
async def main() -> None:
"""Generate image embeddings with Azure AI Inference."""
async with AzureAIInferenceEmbeddingClient() as client:
"""Generate image embeddings with Foundry."""
async with FoundryEmbeddingClient() as client:
# 1. Generate an image embedding.
image_bytes = SAMPLE_IMAGE_PATH.read_bytes()
image_content = Content.from_data(data=image_bytes, media_type="image/jpeg")
+1 -1
View File
@@ -17,7 +17,7 @@ The Model Context Protocol (MCP) is an open standard for connecting AI agents to
## Prerequisites
- `OPENAI_API_KEY` environment variable
- `OPENAI_RESPONSES_MODEL` environment variable
- `OPENAI_CHAT_MODEL` environment variable
Run `mcp_api_key_auth.py` with the MCP API key as the first command-line argument.
@@ -25,7 +25,7 @@ The new usage tracking sample uses `OpenAIChatClient`, so set the usual OpenAI r
```bash
export OPENAI_API_KEY="your-openai-api-key"
export OPENAI_RESPONSES_MODEL="gpt-4.1-mini"
export OPENAI_CHAT_MODEL="gpt-4.1-mini"
```
Then run:
@@ -40,8 +40,8 @@ ENABLE_SENSITIVE_DATA=true
# OpenAI specific variables
# ==========================
OPENAI_API_KEY="..."
OPENAI_RESPONSES_MODEL="gpt-4o-2024-08-06"
OPENAI_CHAT_MODEL="gpt-4o-2024-08-06"
OPENAI_CHAT_COMPLETION_MODEL="gpt-4o-2024-08-06"
# Azure AI Foundry specific variables
# ====================================
+3 -1
View File
@@ -115,7 +115,9 @@ Orchestration-focused samples (Sequential, Concurrent, Handoff, GroupChat, Magen
| Sample | File | Concepts |
| -------------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- |
| State with Agents | [state-management/state_with_agents.py](./state-management/state_with_agents.py) | Store in state once and later reuse across agents |
| Workflow Kwargs (Custom Context) | [state-management/workflow_kwargs.py](./state-management/workflow_kwargs.py) | Pass custom context (data, user tokens) via kwargs to `@tool` tools |
| Workflow Kwargs - Global Context | [state-management/workflow_kwargs_global.py](./state-management/workflow_kwargs_global.py) | Pass custom context (data, user tokens) via kwargs to `@tool` tools in all agents |
| Workflow Kwargs - Per Agent | [state-management/workflow_kwargs_per_agent.py](./state-management/workflow_kwargs_per_agent.py) | Pass custom context (data, user tokens) via kwargs to `@tool` tools in individual agents |
### visualization
@@ -1,6 +1,6 @@
# OpenAI Configuration
OPENAI_API_KEY=
OPENAI_CHAT_MODEL=
OPENAI_CHAT_COMPLETION_MODEL=
# Agent 365 Agentic Authentication Configuration
USE_ANONYMOUS_MODE=
@@ -21,7 +21,7 @@ export USE_ANONYMOUS_MODE=True # set to false if using auth
# OpenAI
export OPENAI_API_KEY="..."
export OPENAI_CHAT_MODEL="..."
export OPENAI_CHAT_COMPLETION_MODEL="..."
```
## Installing Dependencies
+8 -8
View File
@@ -92,10 +92,10 @@ variable.
| --- | --- | --- | --- |
| `agent-framework-anthropic` | `AnthropicClient` | `ANTHROPIC_API_KEY` | `sk-ant-api03-...` |
| `agent-framework-anthropic` | `AnthropicClient` | `ANTHROPIC_CHAT_MODEL` | `claude-sonnet-4-5-20250929` |
| `agent-framework-azure-ai` | `AzureAIInferenceEmbeddingClient` | `AZURE_AI_INFERENCE_ENDPOINT` | `https://my-endpoint.inference.ai.azure.com` |
| `agent-framework-azure-ai` | `AzureAIInferenceEmbeddingClient` | `AZURE_AI_INFERENCE_API_KEY` | `env-key` |
| `agent-framework-azure-ai` | `AzureAIInferenceEmbeddingClient` | `AZURE_AI_INFERENCE_EMBEDDING_MODEL` | `text-embedding-3-small` |
| `agent-framework-azure-ai` | `AzureAIInferenceEmbeddingClient` | `AZURE_AI_INFERENCE_IMAGE_EMBEDDING_MODEL` | `Cohere-embed-v3-english` |
| `agent-framework-foundry` | `FoundryEmbeddingClient` | `FOUNDRY_MODELS_ENDPOINT` | `https://my-endpoint.inference.ai.azure.com` |
| `agent-framework-foundry` | `FoundryEmbeddingClient` | `FOUNDRY_MODELS_API_KEY` | `env-key` |
| `agent-framework-foundry` | `FoundryEmbeddingClient` | `FOUNDRY_EMBEDDING_MODEL` | `text-embedding-3-small` |
| `agent-framework-foundry` | `FoundryEmbeddingClient` | `FOUNDRY_IMAGE_EMBEDDING_MODEL` | `Cohere-embed-v3-english` |
| `agent-framework-azure-ai-search` | `AzureAISearchContextProvider` | `AZURE_SEARCH_ENDPOINT` | `https://my-search.search.windows.net` |
| `agent-framework-azure-ai-search` | `AzureAISearchContextProvider` | `AZURE_SEARCH_API_KEY` | `search-key` |
| `agent-framework-azure-ai-search` | `AzureAISearchContextProvider` | `AZURE_SEARCH_INDEX_NAME` | `hotels-index` |
@@ -144,8 +144,8 @@ variable.
| `agent-framework-ollama` | `OllamaChatClient` | `OLLAMA_MODEL` | `llama3.1:8b` |
| `agent-framework-openai` | `OpenAIChatClient / OpenAIChatCompletionClient / OpenAIEmbeddingClient` | `OPENAI_API_KEY` | `sk-proj-...` |
| `agent-framework-openai` | `OpenAIChatClient / OpenAIChatCompletionClient / OpenAIEmbeddingClient` | `OPENAI_MODEL` | `gpt-4o-mini` |
| `agent-framework-openai` | `OpenAIChatClient` | `OPENAI_RESPONSES_MODEL` | `gpt-4.1-mini` |
| `agent-framework-openai` | `OpenAIChatCompletionClient` | `OPENAI_CHAT_MODEL` | `gpt-4o` |
| `agent-framework-openai` | `OpenAIChatClient` | `OPENAI_CHAT_MODEL` | `gpt-4.1-mini` |
| `agent-framework-openai` | `OpenAIChatCompletionClient` | `OPENAI_CHAT_COMPLETION_MODEL` | `gpt-4o` |
| `agent-framework-openai` | `OpenAIEmbeddingClient` | `OPENAI_EMBEDDING_MODEL` | `text-embedding-3-small` |
| `agent-framework-openai` | `OpenAIChatClient / OpenAIChatCompletionClient / OpenAIEmbeddingClient` | `OPENAI_BASE_URL` | `https://api.openai.com/v1/` |
| `agent-framework-openai` | `OpenAIChatClient / OpenAIChatCompletionClient / OpenAIEmbeddingClient` | `OPENAI_ORG_ID` | `org_123456789` |
@@ -154,8 +154,8 @@ variable.
| `agent-framework-openai` | `OpenAIChatClient / OpenAIChatCompletionClient / OpenAIEmbeddingClient` | `AZURE_OPENAI_API_VERSION` | `2024-10-21` |
| `agent-framework-openai` | `OpenAIChatClient / OpenAIChatCompletionClient / OpenAIEmbeddingClient` | `AZURE_OPENAI_BASE_URL` | `https://my-resource.openai.azure.com/openai/v1/` |
| `agent-framework-openai` | `OpenAIChatClient / OpenAIChatCompletionClient / OpenAIEmbeddingClient` | `AZURE_OPENAI_MODEL` | `gpt-4o` |
| `agent-framework-openai` | `OpenAIChatClient` | `AZURE_OPENAI_RESPONSES_MODEL` | `gpt-4.1` |
| `agent-framework-openai` | `OpenAIChatCompletionClient` | `AZURE_OPENAI_CHAT_MODEL` | `gpt-4o-mini` |
| `agent-framework-openai` | `OpenAIChatClient` | `AZURE_OPENAI_CHAT_MODEL` | `gpt-4.1` |
| `agent-framework-openai` | `OpenAIChatCompletionClient` | `AZURE_OPENAI_CHAT_COMPLETION_MODEL` | `gpt-4o-mini` |
| `agent-framework-openai` | `OpenAIEmbeddingClient` | `AZURE_OPENAI_EMBEDDING_MODEL` | `text-embedding-3-large` |
| `agent-framework-openai` | `OpenAIChatClient / OpenAIChatCompletionClient / OpenAIEmbeddingClient` | `AZURE_OPENAI_RESOURCE_URL` | `https://cognitiveservices.azure.com/` |
+4 -42
View File
@@ -30,7 +30,6 @@ members = [
"agent-framework-a2a",
"agent-framework-ag-ui",
"agent-framework-anthropic",
"agent-framework-azure-ai",
"agent-framework-azure-ai-search",
"agent-framework-azure-cosmos",
"agent-framework-azurefunctions",
@@ -203,31 +202,6 @@ requires-dist = [
{ name = "anthropic", specifier = ">=0.80.0,<0.80.1" },
]
[[package]]
name = "agent-framework-azure-ai"
version = "1.0.0rc6"
source = { editable = "packages/azure-ai" }
dependencies = [
{ name = "agent-framework-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-openai", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "aiohttp", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "azure-ai-agents", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "azure-ai-inference", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "azure-ai-projects", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "azure-identity", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
]
[package.metadata]
requires-dist = [
{ name = "agent-framework-core", editable = "packages/core" },
{ name = "agent-framework-openai", editable = "packages/openai" },
{ name = "aiohttp", specifier = ">=3.7.0,<4" },
{ name = "azure-ai-agents", specifier = ">=1.2.0b5,<1.2.0b6" },
{ name = "azure-ai-inference", specifier = ">=1.0.0b9,<1.0.0b10" },
{ name = "azure-ai-projects", specifier = ">=2.0.0,<3.0" },
{ name = "azure-identity", specifier = ">=1,<2" },
]
[[package]]
name = "agent-framework-azure-ai-search"
version = "1.0.0b260330"
@@ -358,8 +332,8 @@ all = [
{ name = "agent-framework-a2a", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-ag-ui", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-anthropic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-azure-ai", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-azure-ai-search", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-azure-cosmos", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-azurefunctions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-bedrock", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-chatkit", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
@@ -386,8 +360,8 @@ requires-dist = [
{ name = "agent-framework-a2a", marker = "extra == 'all'", editable = "packages/a2a" },
{ name = "agent-framework-ag-ui", marker = "extra == 'all'", editable = "packages/ag-ui" },
{ name = "agent-framework-anthropic", marker = "extra == 'all'", editable = "packages/anthropic" },
{ name = "agent-framework-azure-ai", marker = "extra == 'all'", editable = "packages/azure-ai" },
{ name = "agent-framework-azure-ai-search", marker = "extra == 'all'", editable = "packages/azure-ai-search" },
{ name = "agent-framework-azure-cosmos", marker = "extra == 'all'", editable = "packages/azure-cosmos" },
{ name = "agent-framework-azurefunctions", marker = "extra == 'all'", editable = "packages/azurefunctions" },
{ name = "agent-framework-bedrock", marker = "extra == 'all'", editable = "packages/bedrock" },
{ name = "agent-framework-chatkit", marker = "extra == 'all'", editable = "packages/chatkit" },
@@ -511,6 +485,7 @@ source = { editable = "packages/foundry" }
dependencies = [
{ name = "agent-framework-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-openai", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "azure-ai-inference", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "azure-ai-projects", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
]
@@ -518,6 +493,7 @@ dependencies = [
requires-dist = [
{ name = "agent-framework-core", editable = "packages/core" },
{ name = "agent-framework-openai", editable = "packages/openai" },
{ name = "azure-ai-inference", specifier = ">=1.0.0b9,<1.0.0b10" },
{ name = "azure-ai-projects", specifier = ">=2.0.0,<3.0" },
]
@@ -1020,20 +996,6 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" },
]
[[package]]
name = "azure-ai-agents"
version = "1.2.0b5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "azure-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "isodate", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "typing-extensions", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ed/57/8adeed578fa8984856c67b4229e93a58e3f6024417d448d0037aafa4ee9b/azure_ai_agents-1.2.0b5.tar.gz", hash = "sha256:1a16ef3f305898aac552269f01536c34a00473dedee0bca731a21fdb739ff9d5", size = 394876, upload-time = "2025-09-30T01:55:02.328Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/6d/6d/15070d23d7a94833a210da09d5d7ed3c24838bb84f0463895e5d159f1695/azure_ai_agents-1.2.0b5-py3-none-any.whl", hash = "sha256:257d0d24a6bf13eed4819cfa5c12fb222e5908deafb3cbfd5711d3a511cc4e88", size = 217948, upload-time = "2025-09-30T01:55:04.155Z" },
]
[[package]]
name = "azure-ai-inference"
version = "1.0.0b9"