Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
* @microsoft/agent365-approvers
/.github/ @microsoft/agent365-approvers
/libraries/microsoft-agents-a365-observability-*/ @microsoft/agent365-observability-approvers
/tests/observability/ @microsoft/agent365-observability-approvers
/tests/observability/ @microsoft/agent365-observability-approvers
/libraries/microsoft-agents-a365-notifications/ @microsoft/agent365-tooling-approvers
/libraries/microsoft-agents-a365-tooling*/ @microsoft/agent365-tooling-approvers
/tests/tooling/ @microsoft/agent365-tooling-approvers
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,7 @@ jobs:

- name: Check linting
run: |
uv run --frozen ruff check .
continue-on-error: true
uv run --frozen ruff check . --preview

- name: Check formatting
run: |
Expand Down
36 changes: 35 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,45 @@ Place it before imports with one blank line after.

### Python Conventions

- Type hints preferred (Pydantic models heavily used)
- Type hints required on all function parameters and return types
- Async/await patterns for I/O operations
- Use explicit `None` checks: `if x is not None:` not `if x:`
- Local imports should be moved to top of file
- Return defensive copies of mutable data to protect singletons
- **Async method naming**: Do NOT use `_async` suffix on async methods. The `_async` suffix is only appropriate when providing both sync and async versions of the same method. Since this SDK is async-only, use plain method names (e.g., `send_chat_history_messages` not `send_chat_history_messages_async`)

### Type Hints - NEVER Use `Any`

**CRITICAL: Never use `typing.Any` in this codebase.** Using `Any` defeats the purpose of type checking and can hide bugs. Instead:

1. **Use actual types from external SDKs** - When integrating with external libraries (OpenAI, LangChain, etc.), import and use their actual types:
```python
from agents.memory import Session
from agents.items import TResponseInputItem

async def send_chat_history(self, session: Session) -> OperationResult:
...
```

2. **Use `Union` for known possible types**:
```python
from typing import Union
MessageType = Union[UserMessage, AssistantMessage, SystemMessage, Dict[str, object]]
```

3. **Use `object` for truly unknown types** that you only pass through:
```python
def log_item(item: object) -> None: ...
```

4. **Use `Protocol` only as a last resort** - If external types cannot be found or imported, define a Protocol. However, **confirm with the developer first** before proceeding with this approach, as it may indicate a missing dependency or incorrect understanding of the external API.

**Why this matters:**
- `Any` disables all type checking for that variable
- Bugs that type checkers would catch go unnoticed
- Code readability suffers - developers don't know what types to expect
- Using actual SDK types provides better IDE support and ensures compatibility
- This applies to both production code AND test files

## CI/CD

Expand Down
44 changes: 43 additions & 1 deletion docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,51 @@ Framework-specific adapters for MCP tool integration:
|---------|---------|------------|
| `extensions-agentframework` | Adapt MCP tools to Microsoft Agents SDK | [design.md](../libraries/microsoft-agents-a365-tooling-extensions-agentframework/docs/design.md) |
| `extensions-azureaifoundry` | Azure AI Foundry tool integration | [design.md](../libraries/microsoft-agents-a365-tooling-extensions-azureaifoundry/docs/design.md) |
| `extensions-openai` | OpenAI function calling integration | [design.md](../libraries/microsoft-agents-a365-tooling-extensions-openai/docs/design.md) |
| `extensions-openai` | OpenAI function calling integration and chat history | [design.md](../libraries/microsoft-agents-a365-tooling-extensions-openai/docs/design.md) |
| `extensions-semantickernel` | Semantic Kernel plugin integration | [design.md](../libraries/microsoft-agents-a365-tooling-extensions-semantickernel/docs/design.md) |

#### OpenAI Extension: Chat History API

The OpenAI tooling extension provides methods to send chat history to the MCP platform for real-time threat protection:

**Key Classes:**

| Class | Purpose |
|-------|---------|
| `McpToolRegistrationService` | MCP tool registration and chat history management |

**Methods:**

| Method | Purpose |
|--------|---------|
| `send_chat_history(turn_context, session, limit, options)` | Extract messages from OpenAI Session and send to MCP platform |
| `send_chat_history_messages(turn_context, messages, options)` | Send a list of OpenAI TResponseInputItem messages to MCP platform |

**Usage Example:**

```python
from agents import Agent, Runner
from microsoft_agents_a365.tooling.extensions.openai import McpToolRegistrationService

service = McpToolRegistrationService()
agent = Agent(name="my-agent", model="gpt-4")

# In your agent handler:
async with Runner.run(agent, messages) as result:
session = result.session

# Option 1: Send from Session object
op_result = await service.send_chat_history(turn_context, session)

# Option 2: Send from message list
op_result = await service.send_chat_history_messages(turn_context, messages)

if op_result.succeeded:
print("Chat history sent successfully")
```

The methods convert OpenAI message types to `ChatHistoryMessage` format and delegate to the core `McpToolServerConfigurationService.send_chat_history()` method.

### 6. Notifications (`microsoft-agents-a365-notifications`)

> **Detailed documentation**: [libraries/microsoft-agents-a365-notifications/docs/design.md](../libraries/microsoft-agents-a365-notifications/docs/design.md)
Expand Down
15 changes: 7 additions & 8 deletions generate_dependency_diagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import re
import tomllib
from pathlib import Path
from typing import Dict, List, Set


class PackageInfo:
Expand All @@ -19,16 +18,16 @@ def __init__(self, name: str, package_type: str, path: Path):
self.name = name
self.package_type = package_type
self.path = path
self.dependencies: Set[str] = set()
self.dependencies: set[str] = set()


def read_pyproject_toml(path: Path) -> Dict:
def read_pyproject_toml(path: Path) -> dict:
"""Read and parse a pyproject.toml file."""
with open(path, "rb") as f:
return tomllib.load(f)


def extract_dependencies(pyproject_data: Dict, package_names: Set[str]) -> Set[str]:
def extract_dependencies(pyproject_data: dict, package_names: set[str]) -> set[str]:
"""Extract internal package dependencies from pyproject.toml data."""
dependencies = set()

Expand All @@ -45,7 +44,7 @@ def extract_dependencies(pyproject_data: Dict, package_names: Set[str]) -> Set[s
return dependencies


def generate_mermaid_diagram(packages: List[PackageInfo]) -> str:
def generate_mermaid_diagram(packages: list[PackageInfo]) -> str:
"""Generate a Mermaid diagram from package information."""

# Color scheme based on package types
Expand Down Expand Up @@ -96,7 +95,7 @@ def generate_mermaid_diagram(packages: List[PackageInfo]) -> str:
lines.append(" %% Styling")

# Group packages by type for styling
packages_by_type: Dict[str, List[str]] = {}
packages_by_type: dict[str, list[str]] = {}
for pkg in packages:
if pkg.package_type not in packages_by_type:
packages_by_type[pkg.package_type] = []
Expand Down Expand Up @@ -170,8 +169,8 @@ def main():

# Collect all package names first and cache pyproject data
all_package_names = set()
packages: List[PackageInfo] = []
pyproject_data_cache: Dict[str, Dict] = {}
packages: list[PackageInfo] = []
pyproject_data_cache: dict[str, dict] = {}

for path_str, pkg_type in package_configs:
pyproject_path = repo_root / path_str / "pyproject.toml"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

"""
Microsoft Agent 365 Notifications
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from __future__ import annotations

from collections.abc import Awaitable, Callable, Iterable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from .agent_notification_activity import AgentNotificationActivity
from .email_reference import EmailReference
from .wpx_comment import WpxComment
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from enum import Enum


Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from typing import Any, Optional, Type, TypeVar
from microsoft_agents.activity import Activity
from .notification_types import NotificationTypes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from enum import Enum


Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from typing import Optional, Literal
from microsoft_agents.activity.entity import Entity
from .notification_types import NotificationTypes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from typing import Literal
from microsoft_agents.activity.activity import Activity
from microsoft_agents.activity.entity import Entity
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from enum import Enum


Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from typing import Optional, Literal
from microsoft_agents.activity.entity import Entity
from .notification_types import NotificationTypes
Expand Down
4 changes: 4 additions & 0 deletions libraries/microsoft-agents-a365-notifications/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ target-version = ['py311']
line-length = 100
target-version = "py311"

[tool.ruff.lint.flake8-copyright]
notice-rgx = "# Copyright \\(c\\) Microsoft Corporation\\.\\r?\\n# Licensed under the MIT License\\."
min-file-size = 1

[tool.mypy]
python_version = "3.11"
strict = true
Expand Down
2 changes: 1 addition & 1 deletion libraries/microsoft-agents-a365-notifications/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
helper_path = Path(__file__).parent.parent.parent / "versioning" / "helper"
sys.path.insert(0, str(helper_path))

from setup_utils import get_dynamic_dependencies
from setup_utils import get_dynamic_dependencies # noqa: E402

# Use minimum version strategy:
# - Internal packages get: >= current_base_version (e.g., >= 0.1.0)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Microsoft Agent 365 Python SDK for OpenTelemetry tracing.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import logging
import threading
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Constants for SDK OpenTelemetry implementation.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Execution type enum.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# pip install opentelemetry-sdk opentelemetry-api requests

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

import json
import logging
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from dataclasses import dataclass

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

from enum import Enum

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Data class for invoke agent details.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Middleware components for Microsoft Agent 365 SDK.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Per request baggage builder for OpenTelemetry context propagation.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Base class for OpenTelemetry tracing scopes.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Request class.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Source metadata class.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Tenant details class.
from dataclasses import dataclass
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Data class for tool call details.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

# Tool type enum.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) Microsoft. All rights reserved.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

"""
Trace Processors
Expand Down
Loading