Added CopilotStudioAgent implementation

This commit is contained in:
Dmytro Struk
2025-09-11 15:09:20 -07:00
Unverified
parent 54a9cba305
commit efb19f9959
14 changed files with 653 additions and 24 deletions
+5
View File
@@ -17,3 +17,8 @@ AGENT_FRAMEWORK_ENABLE_SENSITIVE_DATA=true
AGENT_FRAMEWORK_WORKFLOW_ENABLE_OTEL=true
# Mem0
MEM0_API_KEY=""
# Copilot Studio
COPILOTSTUDIOAGENT__ENVIRONMENTID=""
COPILOTSTUDIOAGENT__SCHEMANAME=""
COPILOTSTUDIOAGENT__TENANTID=""
COPILOTSTUDIOAGENT__AGENTAPPID=""
+21
View File
@@ -0,0 +1,21 @@
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
@@ -0,0 +1,13 @@
# Copyright (c) Microsoft. All rights reserved.
import importlib.metadata
from ._acquire_token import acquire_token
from ._agent import CopilotStudioAgent
try:
__version__ = importlib.metadata.version(__name__)
except importlib.metadata.PackageNotFoundError:
__version__ = "0.0.0" # Fallback for development mode
__all__ = ["CopilotStudioAgent", "__version__", "acquire_token"]
@@ -0,0 +1,94 @@
# Copyright (c) Microsoft. All rights reserved.
# pyright: reportUnknownMemberType = false
# pyright: reportUnknownVariableType = false
# pyright: reportUnknownArgumentType = false
import logging
from typing import Any
from agent_framework.exceptions import ServiceException
from msal import PublicClientApplication
logger = logging.getLogger(__name__)
# Default scopes for Power Platform API
DEFAULT_SCOPES = ["https://api.powerplatform.com/.default"]
def acquire_token(
client_id: str,
tenant_id: str,
username: str | None = None,
token_cache: Any | None = None,
scopes: list[str] | None = None,
) -> str:
"""Acquire an authentication token using MSAL Public Client Application.
This function attempts to acquire a token silently first (using cached tokens),
and falls back to interactive authentication if needed.
Args:
client_id: The client ID of the application.
tenant_id: The tenant ID for authentication.
username: Optional username to filter accounts.
token_cache: Optional token cache for storing tokens.
scopes: Optional list of scopes. Defaults to Power Platform API scopes.
Returns:
The access token string.
Raises:
ServiceException: If authentication token cannot be acquired.
"""
if not client_id:
raise ServiceException("Client ID is required for token acquisition.")
if not tenant_id:
raise ServiceException("Tenant ID is required for token acquisition.")
authority = f"https://login.microsoftonline.com/{tenant_id}"
target_scopes = scopes or DEFAULT_SCOPES
pca = PublicClientApplication(client_id=client_id, authority=authority, token_cache=token_cache)
accounts = pca.get_accounts(username=username)
token: str | None = None
# Try silent token acquisition first if we have cached accounts
if accounts:
try:
logger.debug("Attempting silent token acquisition")
response = pca.acquire_token_silent(scopes=target_scopes, account=accounts[0])
if response and "access_token" in response:
token = str(response["access_token"]) # type: ignore[assignment]
logger.debug("Successfully acquired token silently")
elif response and "error" in response:
logger.warning(
"Silent token acquisition failed: %s - %s", response.get("error"), response.get("error_description")
)
except Exception as ex:
logger.warning("Silent token acquisition failed with exception: %s", ex)
# Fall back to interactive authentication if silent acquisition failed
if not token:
try:
logger.debug("Attempting interactive token acquisition")
response = pca.acquire_token_interactive(scopes=target_scopes)
if response and "access_token" in response:
token = str(response["access_token"]) # type: ignore[assignment]
logger.debug("Successfully acquired token interactively")
elif response and "error" in response:
logger.error(
"Interactive token acquisition failed: %s - %s",
response.get("error"),
response.get("error_description"),
)
except Exception as ex:
logger.error("Interactive token acquisition failed with exception: %s", ex)
raise ServiceException(f"Failed to acquire authentication token: {ex}") from ex
if not token:
raise ServiceException("Authentication token cannot be acquired.")
return token
@@ -0,0 +1,282 @@
# Copyright (c) Microsoft. All rights reserved.
from collections.abc import AsyncIterable, MutableSequence
from typing import Any, ClassVar
from agent_framework import (
AgentRunResponse,
AgentRunResponseUpdate,
AgentThread,
BaseAgent,
ChatMessage,
Contents,
Role,
TextContent,
TextReasoningContent,
)
from agent_framework._pydantic import AFBaseSettings
from agent_framework.exceptions import ServiceException, ServiceInitializationError
from microsoft_agents.activity import Activity
from microsoft_agents.copilotstudio.client import AgentType, ConnectionSettings, CopilotClient, PowerPlatformCloud
from pydantic import ValidationError
from ._acquire_token import acquire_token
class CopilotStudioSettings(AFBaseSettings):
"""Copilot Studio model settings.
The settings are first loaded from environment variables with the prefix 'COPILOTSTUDIOAGENT__'.
If the environment variables are not found, the settings can be loaded from a .env file
with the encoding 'utf-8'. If the settings are not found in the .env file, the settings
are ignored; however, validation will fail alerting that the settings are missing.
Attributes:
environment_id: Environment ID of environment with the Copilot Studio App..
(Env var COPILOTSTUDIOAGENT__ENVIRONMENTID)
agent_identifier: The agent identifier or schema name of the Copilot to use.
(Env var COPILOTSTUDIOAGENT__SCHEMANAME)
client_id: The app ID of the App Registration used to login.
(Env var COPILOTSTUDIOAGENT__AGENTAPPID)
tenant_id: The tenant ID of the App Registration used to login.
(Env var COPILOTSTUDIOAGENT__TENANTID)
Parameters:
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'.
"""
env_prefix: ClassVar[str] = "COPILOTSTUDIOAGENT__"
environment_id: str | None = None
agent_identifier: str | None = None
client_id: str | None = None
tenant_id: str | None = None
class CopilotStudioAgent(BaseAgent):
"""A Copilot Studio Agent."""
client: CopilotClient
settings: ConnectionSettings | None
environment_id: str | None
agent_identifier: str | None
client_id: str | None
tenant_id: str | None
token: str | None
cloud: PowerPlatformCloud | None
agent_type: AgentType | None
custom_power_platform_cloud: str | None
username: str | None
token_cache: Any | None
scopes: list[str] | None
def __init__(
self,
client: CopilotClient | None = None,
settings: ConnectionSettings | None = None,
environment_id: str | None = None,
agent_identifier: str | None = None,
client_id: str | None = None,
tenant_id: str | None = None,
token: str | None = None,
cloud: PowerPlatformCloud | None = None,
agent_type: AgentType | None = None,
custom_power_platform_cloud: str | None = None,
username: str | None = None,
token_cache: Any | None = None,
scopes: list[str] | None = None,
env_file_path: str | None = None,
env_file_encoding: str | None = None,
) -> None:
if not client:
try:
copilot_studio_settings = CopilotStudioSettings(
environment_id=environment_id,
agent_identifier=agent_identifier,
client_id=client_id,
tenant_id=tenant_id,
env_file_path=env_file_path,
env_file_encoding=env_file_encoding,
)
except ValidationError as ex:
raise ServiceInitializationError("Failed to create Copilot Studio settings.", ex) from ex
if not settings:
if not copilot_studio_settings.environment_id:
raise ServiceInitializationError(
"Copilot Studio environment ID is required. Set via 'environment_id' parameter "
"or 'COPILOTSTUDIOAGENT__ENVIRONMENTID' environment variable."
)
if not copilot_studio_settings.agent_identifier:
raise ServiceInitializationError(
"Copilot Studio agent identifier/schema name is required. Set via 'agent_identifier' parameter "
"or 'COPILOTSTUDIOAGENT__SCHEMANAME' environment variable."
)
settings = ConnectionSettings(
environment_id=copilot_studio_settings.environment_id,
agent_identifier=copilot_studio_settings.agent_identifier,
cloud=cloud,
copilot_agent_type=agent_type,
custom_power_platform_cloud=custom_power_platform_cloud,
)
if not token:
if not copilot_studio_settings.client_id:
raise ServiceInitializationError(
"Copilot Studio client ID is required. Set via 'client_id' parameter "
"or 'COPILOTSTUDIOAGENT__AGENTAPPID' environment variable."
)
if not copilot_studio_settings.tenant_id:
raise ServiceInitializationError(
"Copilot Studio tenant ID is required. Set via 'tenant_id' parameter "
"or 'COPILOTSTUDIOAGENT__TENANTID' environment variable."
)
token = acquire_token(
client_id=copilot_studio_settings.client_id,
tenant_id=copilot_studio_settings.tenant_id,
username=username,
token_cache=token_cache,
scopes=scopes,
)
client = CopilotClient(settings=settings, token=token)
super().__init__(
client=client, # type: ignore[reportCallIssue]
settings=settings, # type: ignore[reportCallIssue]
environment_id=copilot_studio_settings.environment_id, # type: ignore[reportCallIssue]
agent_identifier=copilot_studio_settings.agent_identifier, # type: ignore[reportCallIssue]
client_id=copilot_studio_settings.client_id, # type: ignore[reportCallIssue]
tenant_id=copilot_studio_settings.tenant_id, # type: ignore[reportCallIssue]
token=token, # type: ignore[reportCallIssue]
cloud=cloud, # type: ignore[reportCallIssue]
agent_type=agent_type, # type: ignore[reportCallIssue]
custom_power_platform_cloud=custom_power_platform_cloud, # type: ignore[reportCallIssue]
username=username, # type: ignore[reportCallIssue]
token_cache=token_cache, # type: ignore[reportCallIssue]
scopes=scopes, # type: ignore[reportCallIssue]
)
async def run(
self,
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
*,
thread: AgentThread | None = None,
**kwargs: Any,
) -> AgentRunResponse:
"""Get a response from the agent.
This method returns the final result of the agent's execution
as a single AgentRunResponse object. The caller is blocked until
the final result is available.
Note: For streaming responses, use the run_stream method, which returns
intermediate steps and the final result as a stream of AgentRunResponseUpdate
objects. Streaming only the final result is not feasible because the timing of
the final result's availability is unknown, and blocking the caller until then
is undesirable in streaming scenarios.
Args:
messages: The message(s) to send to the agent.
thread: The conversation thread associated with the message(s).
kwargs: Additional keyword arguments.
Returns:
An agent response item.
"""
if not thread:
thread = self.get_new_thread()
thread.service_thread_id = await self._start_new_conversation()
input_messages = self._normalize_messages(messages)
question = "\n".join([message.text for message in input_messages])
activities = self.client.ask_question(question, thread.service_thread_id)
response_messages: list[ChatMessage] = []
response_id: str | None = None
async for message in self._process_activities(activities):
response_messages.append(message)
if not response_id:
response_id = message.message_id
return AgentRunResponse(messages=response_messages, response_id=response_id)
async def run_stream(
self,
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
*,
thread: AgentThread | None = None,
**kwargs: Any,
) -> AsyncIterable[AgentRunResponseUpdate]:
"""Run the agent as a stream.
This method will return the intermediate steps and final results of the
agent's execution as a stream of AgentRunResponseUpdate objects to the caller.
Note: An AgentRunResponseUpdate object contains a chunk of a message.
Args:
messages: The message(s) to send to the agent.
thread: The conversation thread associated with the message(s).
kwargs: Additional keyword arguments.
Yields:
An agent response item.
"""
if not thread:
thread = self.get_new_thread()
thread.service_thread_id = await self._start_new_conversation()
input_messages = self._normalize_messages(messages)
question = "\n".join([message.text for message in input_messages])
activities = self.client.ask_question(question, thread.service_thread_id)
async for message in self._process_activities(activities):
yield AgentRunResponseUpdate(
role=message.role,
contents=message.contents,
additional_properties=message.additional_properties,
author_name=message.author_name,
raw_representation=message.raw_representation,
response_id=message.message_id,
message_id=message.message_id,
)
async def _start_new_conversation(self) -> str:
conversation_id: str | None = None
async for activity in self.client.start_conversation(emit_start_conversation_event=True):
if activity and activity.conversation and activity.conversation.id:
conversation_id = activity.conversation.id
if not conversation_id:
raise ServiceException("Failed to start a new conversation.")
return conversation_id
async def _process_activities(self, activities: AsyncIterable[Activity]) -> AsyncIterable[ChatMessage]:
async for activity in activities:
if activity.type == "message":
yield self._create_chat_message_from_activity(activity, [TextContent(activity.text)])
break
elif activity.type == "typing" or activity.type == "event":
yield self._create_chat_message_from_activity(activity, [TextReasoningContent(activity.text)])
break
def _create_chat_message_from_activity(
self, activity: Activity, contents: MutableSequence[Contents]
) -> ChatMessage:
return ChatMessage(
role=Role.ASSISTANT,
contents=contents,
author_name=activity.from_property.name if activity.from_property else None,
message_id=activity.id,
raw_representation=activity,
)
@@ -0,0 +1,94 @@
[project]
name = "agent-framework-copilotstudio"
description = "Copilot Studio integration for Microsoft Agent Framework."
authors = [{ name = "Microsoft", email = "SK-Support@microsoft.com"}]
readme = "README.md"
requires-python = ">=3.10"
version = "0.1.0b1"
license-files = ["LICENSE"]
urls.homepage = "https://learn.microsoft.com/en-us/semantic-kernel/overview/"
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 :: 5 - Production/Stable",
"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",
"Framework :: Pydantic :: 2",
"Typing :: Typed",
]
dependencies = [
"agent-framework",
"microsoft-agents-copilotstudio-client>=0.3.1",
]
[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 = [
"ignore:Support for class-based `config` is deprecated:DeprecationWarning:pydantic.*"
]
timeout = 120
[tool.ruff]
extend = "../../pyproject.toml"
[tool.coverage.run]
omit = [
"**/__init__.py"
]
[tool.pyright]
extend = "../../pyproject.toml"
exclude = ['tests']
[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
disallow_any_unimported = true
[tool.bandit]
targets = ["agent_framework_copilotstudio"]
exclude_dirs = ["tests"]
[tool.poe]
executor.type = "uv"
include = "../../shared_tasks.toml"
[tool.poe.tasks]
mypy = "mypy --config-file $POE_ROOT/pyproject.toml agent_framework_copilotstudio"
test = "pytest --cov=agent_framework_copilotstudio --cov-report=term-missing:skip-covered tests"
[tool.uv.build-backend]
module-name = "agent_framework_copilotstudio"
module-root = ""
[build-system]
requires = ["uv_build>=0.8.2,<0.9.0"]
build-backend = "uv_build"
@@ -0,0 +1,28 @@
# Copyright (c) Microsoft. All rights reserved.
def test_self_through_main() -> None:
try:
from agent_framework.copilotstudio import __version__
except ImportError:
__version__ = None
assert __version__ is not None
def test_self() -> None:
try:
from agent_framework_copilotstudio import __version__
except ImportError:
__version__ = None
assert __version__ is not None
def test_agent_framework() -> None:
try:
from agent_framework import __version__
except ImportError:
__version__ = None
assert __version__ is not None
+15 -15
View File
@@ -170,6 +170,21 @@ class BaseAgent(AFBaseModel):
await deserialize_thread_state(thread, serialized_thread, **kwargs)
return thread
def _normalize_messages(
self,
messages: str | ChatMessage | Sequence[str] | Sequence[ChatMessage] | None = None,
) -> list[ChatMessage]:
if messages is None:
return []
if isinstance(messages, str):
return [ChatMessage(role=Role.USER, text=messages)]
if isinstance(messages, ChatMessage):
return [messages]
return [ChatMessage(role=Role.USER, text=msg) if isinstance(msg, str) else msg for msg in messages]
# region ChatAgent
@@ -669,21 +684,6 @@ class ChatAgent(BaseAgent):
messages.extend(input_messages or [])
return thread, messages
def _normalize_messages(
self,
messages: str | ChatMessage | Sequence[str] | Sequence[ChatMessage] | None = None,
) -> list[ChatMessage]:
if messages is None:
return []
if isinstance(messages, str):
return [ChatMessage(role=Role.USER, text=messages)]
if isinstance(messages, ChatMessage):
return [messages]
return [ChatMessage(role=Role.USER, text=msg) if isinstance(msg, str) else msg for msg in messages]
def _get_agent_name(self) -> str:
return self.name or "UnnamedAgent"
@@ -0,0 +1,24 @@
# Copyright (c) Microsoft. All rights reserved.
import importlib
from typing import Any
PACKAGE_NAME = "agent_framework_copilotstudio"
PACKAGE_EXTRA = "copilotstudio"
_IMPORTS = ["CopilotStudioAgent", "__version__", "acquire_token"]
def __getattr__(name: str) -> Any:
if name in _IMPORTS:
try:
return getattr(importlib.import_module(PACKAGE_NAME), name)
except ModuleNotFoundError as exc:
raise ModuleNotFoundError(
f"The '{PACKAGE_EXTRA}' extra is not installed, "
f"please do `pip install agent-framework[{PACKAGE_EXTRA}]`"
) from exc
raise AttributeError(f"Module {PACKAGE_NAME} has no attribute {name}.")
def __dir__() -> list[str]:
return _IMPORTS
@@ -0,0 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
from agent_framework_copilotstudio import CopilotStudioAgent, __version__, acquire_token
__all__ = ["CopilotStudioAgent", "__version__", "acquire_token"]
@@ -2,7 +2,7 @@
import logging
import uuid
from collections.abc import AsyncIterable
from collections.abc import AsyncIterable, Sequence
from datetime import datetime
from typing import TYPE_CHECKING, Any, ClassVar, TypedDict, cast
@@ -199,7 +199,7 @@ class WorkflowAgent(BaseAgent):
def _normalize_messages(
self,
messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
messages: str | ChatMessage | Sequence[str] | Sequence[ChatMessage] | None = None,
) -> list[ChatMessage]:
"""Normalize input messages to a list of ChatMessage objects."""
if messages is None:
@@ -211,7 +211,7 @@ class WorkflowAgent(BaseAgent):
if isinstance(messages, ChatMessage):
return [messages]
normalized = []
normalized: list[ChatMessage] = []
for msg in messages:
if isinstance(msg, str):
normalized.append(ChatMessage(role=Role.USER, contents=[TextContent(text=msg)]))
+3 -1
View File
@@ -6,6 +6,7 @@ requires-python = ">=3.10"
dependencies = [
"agent-framework",
"agent-framework-azure",
"agent-framework-copilotstudio",
"agent-framework-foundry",
"agent-framework-mem0",
"agent-framework-workflow",
@@ -63,6 +64,7 @@ exclude = [ "packages/agent_framework_project.egg-info" ]
[tool.uv.sources]
agent-framework = { workspace = true }
agent-framework-azure = { workspace = true }
agent-framework-copilotstudio = { workspace = true }
agent-framework-foundry = { workspace = true }
agent-framework-mem0 = { workspace = true }
agent-framework-runtime = { workspace = true }
@@ -193,7 +195,7 @@ build = "python run_tasks_in_packages_if_exists.py build"
# combined checks
check = ["fmt", "lint", "pyright", "mypy", "test", "markdown-code-lint", "samples-code-check"]
pre-commit-check = ["fmt", "lint", "pyright", "markdown-code-lint", "samples-code-check"]
all-tests = "pytest --import-mode=importlib --cov=agent_framework --cov=agent_framework_azure --cov=agent_framework_foundry --cov=agent_framework_mem0 --cov=agent_framework_workflow --cov-report=term-missing:skip-covered packages/azure/tests packages/foundry/tests packages/main/tests packages/mem0/tests packages/workflow/tests"
all-tests = "pytest --import-mode=importlib --cov=agent_framework --cov=agent_framework_azure --cov=agent_framework_foundry --cov=agent_framework_mem0 --cov=agent_framework_workflow --cov-report=term-missing:skip-covered packages/azure/tests packages/copilotstudio/tests packages/foundry/tests packages/main/tests packages/mem0/tests packages/workflow/tests"
[tool.poe.tasks.venv]
cmd = "uv venv --clear --python $python"
+66 -5
View File
@@ -25,6 +25,7 @@ supported-markers = [
members = [
"agent-framework",
"agent-framework-azure",
"agent-framework-copilotstudio",
"agent-framework-foundry",
"agent-framework-mem0",
"agent-framework-project",
@@ -51,7 +52,7 @@ source = { editable = "packages/main" }
dependencies = [
{ name = "azure-monitor-opentelemetry", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "azure-monitor-opentelemetry-exporter", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "mcp", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "mcp", extra = ["ws"], marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "openai", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "opentelemetry-api", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "opentelemetry-exporter-otlp-proto-grpc", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
@@ -59,7 +60,6 @@ dependencies = [
{ name = "pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "pydantic-settings", 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'" },
{ name = "websockets", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
]
[package.optional-dependencies]
@@ -84,7 +84,7 @@ requires-dist = [
{ name = "agent-framework-workflow", marker = "extra == 'workflow'", editable = "packages/workflow" },
{ name = "azure-monitor-opentelemetry", specifier = ">=1.7.0" },
{ name = "azure-monitor-opentelemetry-exporter", specifier = ">=1.0.0b41" },
{ name = "mcp", specifier = ">=1.12" },
{ name = "mcp", extras = ["ws"], specifier = ">=1.13" },
{ name = "openai", specifier = ">=1.99.0" },
{ name = "opentelemetry-api", specifier = "~=1.24" },
{ name = "opentelemetry-exporter-otlp-proto-grpc", specifier = ">=1.36.0" },
@@ -92,7 +92,6 @@ requires-dist = [
{ name = "pydantic", specifier = ">=2.11.7" },
{ name = "pydantic-settings", specifier = ">=2.10.1" },
{ name = "typing-extensions", specifier = ">=4.14.0" },
{ name = "websockets", specifier = ">=15.0.1" },
]
provides-extras = ["azure", "foundry", "workflow", "runtime"]
@@ -111,6 +110,21 @@ requires-dist = [
{ name = "azure-identity", specifier = ">=1.13" },
]
[[package]]
name = "agent-framework-copilotstudio"
version = "0.1.0b1"
source = { editable = "packages/copilotstudio" }
dependencies = [
{ name = "agent-framework", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "microsoft-agents-copilotstudio-client", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
]
[package.metadata]
requires-dist = [
{ name = "agent-framework", editable = "packages/main" },
{ name = "microsoft-agents-copilotstudio-client", specifier = ">=0.3.1" },
]
[[package]]
name = "agent-framework-foundry"
version = "0.1.0b1"
@@ -152,6 +166,7 @@ source = { virtual = "." }
dependencies = [
{ name = "agent-framework", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-azure", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-copilotstudio", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-foundry", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-mem0", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "agent-framework-workflow", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
@@ -196,6 +211,7 @@ dev = [
requires-dist = [
{ name = "agent-framework", editable = "packages/main" },
{ name = "agent-framework-azure", editable = "packages/azure" },
{ name = "agent-framework-copilotstudio", editable = "packages/copilotstudio" },
{ name = "agent-framework-foundry", editable = "packages/foundry" },
{ name = "agent-framework-mem0", editable = "packages/mem0" },
{ name = "agent-framework-workflow", editable = "packages/workflow" },
@@ -1052,7 +1068,7 @@ name = "exceptiongroup"
version = "1.3.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "typing-extensions", marker = "(python_full_version < '3.13' and sys_platform == 'darwin') or (python_full_version < '3.13' and sys_platform == 'linux') or (python_full_version < '3.13' and sys_platform == 'win32')" },
{ name = "typing-extensions", marker = "(python_full_version < '3.11' and sys_platform == 'darwin') or (python_full_version < '3.11' and sys_platform == 'linux') or (python_full_version < '3.11' and sys_platform == 'win32')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749 }
wheels = [
@@ -1860,6 +1876,11 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/19/3f/d085c7f49ade6d273b185d61ec9405e672b6433f710ea64a90135a8dd445/mcp-1.13.1-py3-none-any.whl", hash = "sha256:c314e7c8bd477a23ba3ef472ee5a32880316c42d03e06dcfa31a1cc7a73b65df", size = 161494 },
]
[package.optional-dependencies]
ws = [
{ name = "websockets", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
]
[[package]]
name = "mdit-py-plugins"
version = "0.5.0"
@@ -1899,6 +1920,46 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/5b/f4/7fb9974bb1f81afb363a6b5a74f64609bf8e021d0cfe486909c6db6a8f3b/mem0ai-0.1.117-py3-none-any.whl", hash = "sha256:12159d6b9fef22a155f9b8b305999c52dfad20a46e7ccbced68677b6f48d4b57", size = 213063 },
]
[[package]]
name = "microsoft-agents-activity"
version = "0.3.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/5a/6a/dfc2fc0316b7dc4f6d24792b4a31a873b026be76792af1e0c3e65f843ef0/microsoft_agents_activity-0.3.1.tar.gz", hash = "sha256:c7567fc30f8e6f2a2d74cd65a1f7f31ade0d7ec9dd94531677d0d7b0648c77ee", size = 44886 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/25/8b/50ce2243e2900e94358f37009121145bb8224a388d95d704856aa2686667/microsoft_agents_activity-0.3.1-py3-none-any.whl", hash = "sha256:d7fc2e9cf2843ec8d6d42608b808b159a12cbb61e1fc7d7b1aaf29899f20746a", size = 111904 },
]
[[package]]
name = "microsoft-agents-copilotstudio-client"
version = "0.3.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "microsoft-agents-hosting-core", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/e9/a5/2381ffd14d6a584f9f7ab80c7b6c634f658ea651b38702eb403c930d8396/microsoft_agents_copilotstudio_client-0.3.1.tar.gz", hash = "sha256:c529209241c9d11b7a6e8696f96a3d43121c10b49e44f00e5066f9cf5256f4f3", size = 5024 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/97/35/8b4e9c691f2ce89653007f358519bbadff1fe0d495c3723c9dbbfa962a33/microsoft_agents_copilotstudio_client-0.3.1-py3-none-any.whl", hash = "sha256:cac7485405325b990202452c9c14848cbdb25d13e6cdaf7bd3eca3a5c1fb3989", size = 7420 },
]
[[package]]
name = "microsoft-agents-hosting-core"
version = "0.3.1"
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 = "microsoft-agents-activity", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "pyjwt", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
{ name = "python-dotenv", marker = "sys_platform == 'darwin' or sys_platform == 'linux' or sys_platform == 'win32'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/6a/14/a1365e0bab1486c2d16aabeb192ca90715794edf4e68be4815c245884420/microsoft_agents_hosting_core-0.3.1.tar.gz", hash = "sha256:0b76bda10e7a54ff3c86e56cbabaad5ac7a4c2a076c9833af3b2f4c86fa85e89", size = 81137 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f0/1b/543ddaa2daf8593911a02a07a6a78366d4a6a0053ec86a557c19fa97b60e/microsoft_agents_hosting_core-0.3.1-py3-none-any.whl", hash = "sha256:a4b41556b15321b74f539c5a0a89f70955459b7ec57e9e4b24e61bba27f1cbbc", size = 94573 },
]
[[package]]
name = "msal"
version = "1.33.0"