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
39 changes: 16 additions & 23 deletions python/agent-framework/sample-agent/.env.template
Original file line number Diff line number Diff line change
@@ -1,56 +1,49 @@
# This is a demo .env file

# OpenAI Configuration
# Replace with your actual OpenAI API key
OPENAI_API_KEY=
OPENAI_MODEL=gpt-4o

# MCP Server Configuration
MCP_SERVER_PORT=8000
MCP_SERVER_HOST=localhost
MCP_PLATFORM_ENDPOINT=https://test.agent365.svc.cloud.dev.microsoft

MCP_SERVER_HOST=
MCP_PLATFORM_ENDPOINT=
# Logging

LOG_LEVEL=INFO

# Observability Configuration
OBSERVABILITY_SERVICE_NAME=agent-framework-sample
OBSERVABILITY_SERVICE_NAMESPACE=agent-framework.samples

# Environment Configuration
# OBO Default-6e8b84fa-ae41-4a00-9ad1-934b73e5d73c
# Agentic auth - Default-5369a35c-46a5-4677-8ff9-2e65587654e7

ENV_ID=
BEARER_TOKEN=
OPENAI_MODEL=

# Authentication Mode
#USE_ENVIRONMENT_ID=false
USE_AGENTIC_AUTH=true

# Agentic Authentication Scope
AGENTIC_AUTH_SCOPE=05879165-0320-489e-b644-f72b33f3edf0/.default

AGENTIC_AUTH_SCOPE=
AGENT_ID=

# Agent365 Agentic Authentication Configuration
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID=
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET=
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID=
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__SCOPES=https://api.botframework.com/.default
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__SCOPES=

AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__AGENTIC__SETTINGS__TYPE=AgenticUserAuthorization
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__AGENTIC__SETTINGS__SCOPES=https://graph.microsoft.com/.default
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__AGENTIC__SETTINGS__ALTERNATEBLUEPRINTCONNECTIONNAME=https://graph.microsoft.com/.default

CONNECTIONSMAP_0_SERVICEURL=*
CONNECTIONSMAP_0_CONNECTION=SERVICE_CONNECTION

# Optional: Server Configuration
PORT=3978

# Azure OpenAI Configuration
AZURE_OPENAI_API_KEY=
AZURE_OPENAI_ENDPOINT=
AZURE_OPENAI_DEPLOYMENT="gpt-4o"
AZURE_OPENAI_API_VERSION="2024-02-01"
AZURE_OPENAI_DEPLOYMENT=
AZURE_OPENAI_API_VERSION=

# Required for observability SDK
ENABLE_OBSERVABILITY=true
Expand Down
106 changes: 106 additions & 0 deletions python/agent-framework/sample-agent/AGENT-CODE-WALKTHROUGH.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Step-by-step walkthrough of the complete agent implementation in `sample_agent\a
|-----------|---------|
| **AgentFramework SDK** | Core AI orchestration and conversation management |
| **Microsoft 365 Agents SDK** | Enterprise hosting and authentication integration |
| **Agent Notifications** | Handle @mentions from Outlook, Word, and Excel |
| **MCP Servers** | External tool access and integration |
| **Microsoft Agent 365 Observability** | Comprehensive tracing and monitoring |

Expand Down Expand Up @@ -43,6 +44,9 @@ from agent_interface import AgentInterface
from local_authentication_options import LocalAuthenticationOptions
from microsoft_agents.hosting.core import Authorization, TurnContext

# Notifications
from microsoft_agents_a365.notifications.agent_notification import NotificationTypes

# Observability Components
from microsoft_agents_a365.observability.core.config import configure

Expand All @@ -57,6 +61,7 @@ from microsoft_agents_a365.tooling.extensions.agentframework.services.mcp_tool_r
**Key Imports**:
- **AgentFramework**: Tools to talk to AI models and manage conversations
- **Microsoft 365 Agents**: Enterprise security and hosting features
- **Notifications**: Handle @mentions from Outlook, Word, and Excel
- **MCP Tooling**: Connects the agent to external tools and services
- **Observability**: Tracks what the agent is doing for monitoring and debugging

Expand Down Expand Up @@ -298,6 +303,107 @@ The agent supports multiple authentication modes and extensive configuration opt

## Step 7: Message Processing

```python
async def process_user_message(
self, message: str, auth: Authorization, context: TurnContext
) -> str:
"""Process user message using the AgentFramework SDK"""
try:
await self.setup_mcp_servers(auth, context)
result = await self.agent.run(message)
return self._extract_result(result) or "I couldn't process your request at this time."
except Exception as e:
logger.error(f"Error processing message: {e}")
return f"Sorry, I encountered an error: {str(e)}"
```

**What it does**: Handles regular chat messages from users.

**What happens**:
1. **Setup Tools**: Makes sure MCP tools are connected (only runs once on first message)
2. **Run Agent**: Sends the message to the AI agent for processing
3. **Extract Response**: Pulls out the text response from the agent's result
4. **Error Handling**: Catches problems and returns friendly error messages

---

## Step 8: Notification Handling

```python
async def handle_agent_notification_activity(
self, notification_activity, auth: Authorization, context: TurnContext
) -> str:
"""Handle agent notification activities (email, Word mentions, etc.)"""
try:
notification_type = notification_activity.notification_type
logger.info(f"📬 Processing notification: {notification_type}")

await self.setup_mcp_servers(auth, context)

# Handle Email Notifications
if notification_type == NotificationTypes.EMAIL_NOTIFICATION:
if not hasattr(notification_activity, "email") or not notification_activity.email:
return "I could not find the email notification details."

email = notification_activity.email
email_body = getattr(email, "html_body", "") or getattr(email, "body", "")
message = f"You have received the following email. Please follow any instructions in it. {email_body}"

result = await self.agent.run(message)
return self._extract_result(result) or "Email notification processed."

# Handle Word Comment Notifications
elif notification_type == NotificationTypes.WPX_COMMENT:
if not hasattr(notification_activity, "wpx_comment") or not notification_activity.wpx_comment:
return "I could not find the Word notification details."

wpx = notification_activity.wpx_comment
doc_id = getattr(wpx, "document_id", "")
comment_id = getattr(wpx, "initiating_comment_id", "")
drive_id = "default"

# Get Word document content
doc_message = f"You have a new comment on the Word document with id '{doc_id}', comment id '{comment_id}', drive id '{drive_id}'. Please retrieve the Word document as well as the comments and return it in text format."
doc_result = await self.agent.run(doc_message)
word_content = self._extract_result(doc_result)

# Process the comment with document context
comment_text = notification_activity.text or ""
response_message = f"You have received the following Word document content and comments. Please refer to these when responding to comment '{comment_text}'. {word_content}"
result = await self.agent.run(response_message)
return self._extract_result(result) or "Word notification processed."

# Generic notification handling
else:
notification_message = notification_activity.text or f"Notification received: {notification_type}"
result = await self.agent.run(notification_message)
return self._extract_result(result) or "Notification processed successfully."

except Exception as e:
logger.error(f"Error processing notification: {e}")
return f"Sorry, I encountered an error processing the notification: {str(e)}"
```

**What it does**: Handles notifications from Microsoft 365 apps like Outlook and Word.

**What happens**:
1. **Setup Tools**: Makes sure MCP tools are connected (notifications might arrive before any regular messages)
2. **Identify Type**: Checks what kind of notification it is (email, Word comment, etc.)
3. **Email Notifications**: Extracts email body and processes with the agent
4. **Word Comments**: Retrieves document content, then processes the comment with context
5. **Generic Handling**: Falls back to simple text processing for other notification types

**Supported Notification Types**:
- `NotificationTypes.EMAIL_NOTIFICATION`: @mentions in Outlook emails
- `NotificationTypes.WPX_COMMENT`: @mentions in Word/Excel comments
- Other notification types handled generically

**Why MCP Setup is Needed**: Notifications need access to tools (like Microsoft Graph to read documents) just like regular messages. The `mcp_servers_initialized` flag ensures setup only runs once regardless of whether a message or notification arrives first.

---

## Step 9: Cleanup

```python
async def initialize(self):
"""Initialize the agent and MCP server connections"""
Expand Down
Loading