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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ ScaffoldingReadMe.txt
~$*
*~
CodeCoverage/
driving_safety_report.md


# MSBuild Binary and Structured Log
*.
Expand Down
122 changes: 90 additions & 32 deletions python/crewai/sample_agent/.env.template
Original file line number Diff line number Diff line change
@@ -1,54 +1,112 @@
# Demo environment for CrewAI hosted agent
# =============================================================================
# CrewAI Agent Sample - Environment Configuration
# =============================================================================
# Copy this file to .env and fill in your values.
# Lines starting with # are comments. Remove # to enable a variable.
# =============================================================================

# -----------------------------------------------------------------------------
# OPENAI / AZURE OPENAI CONFIGURATION
# -----------------------------------------------------------------------------
# Choose ONE of the following configurations:

# Option A: Standard OpenAI
# Get your API key from https://platform.openai.com/api-keys
OPENAI_API_KEY=

# MCP Server Configuration
MCP_SERVER_PORT=8000
MCP_SERVER_HOST=localhost
MCP_DEVELOPMENT_BASE_URL=
# Option B: Azure OpenAI (recommended for enterprise)
# Get these values from Azure Portal > Your OpenAI Resource > Keys and Endpoint
AZURE_API_KEY=
AZURE_API_BASE=
AZURE_API_VERSION=2025-01-01-preview

# Model Configuration
# For Azure OpenAI: Use "azure/<deployment-name>" format (e.g., azure/gpt-4.1)
# For OpenAI: Use model name directly (e.g., gpt-4o-mini)
OPENAI_MODEL_NAME=azure/gpt-4.1

# -----------------------------------------------------------------------------
# MCP (MODEL CONTEXT PROTOCOL) AUTHENTICATION
# -----------------------------------------------------------------------------
# These settings enable MCP tools like Mail, Calendar, and Copilot

# Bearer Token for MCP Server Authentication
# Generate with: a365 develop get-token -o raw
# This token expires - regenerate when you see MCP connection errors
BEARER_TOKEN=

# Logging
LOG_LEVEL=INFO
# Agentic Authentication Mode
# Set to "false" for local development with bearer token
# Set to "true" for production with full app registration
USE_AGENTIC_AUTH=false

# Observability Configuration
OBSERVABILITY_SERVICE_NAME=crewai-agent-sample
# Agent identifiers
# AGENT_ID is the primary identifier used by the backend for observability.
# If not set, the application automatically falls back to using AGENTIC_APP_ID.
AGENT_ID=

# Agent Application ID (used for MCP tool discovery and as the default agent ID)
# This identifies your agent when connecting to MCP servers
AGENTIC_APP_ID=crewai-agent

# -----------------------------------------------------------------------------
# TAVILY API - WEATHER SEARCH TOOL
# -----------------------------------------------------------------------------
# Required for the WeatherTool to search current weather conditions
# Get your free API key from https://tavily.com
TAVILY_API_KEY=

# -----------------------------------------------------------------------------
# OBSERVABILITY CONFIGURATION
# -----------------------------------------------------------------------------
# These settings configure Agent 365 observability tracing

# Service identifiers for telemetry
OBSERVABILITY_SERVICE_NAME=crewai-agent-sample
OBSERVABILITY_SERVICE_NAMESPACE=agent365-samples

# Enable/disable observability features
ENABLE_OBSERVABILITY=true

BEARER_TOKEN=
# Enable Agent 365 cloud exporter (requires valid token)
# Set to "true" to send traces to Agent 365 observability backend
ENABLE_A365_OBSERVABILITY_EXPORTER=false

OPENAI_MODEL=gpt-4o-mini
# Python environment indicator
PYTHON_ENVIRONMENT=development

USE_AGENTIC_AUTH=false
# -----------------------------------------------------------------------------
# SERVER CONFIGURATION
# -----------------------------------------------------------------------------
# The port the agent server listens on
# If busy, the server will automatically try the next available port
PORT=3978

AGENTIC_APP_ID=
# Logging verbosity: DEBUG, INFO, WARNING, ERROR
LOG_LEVEL=INFO

# Agent observability attributes (optional but recommended)
# These populate the gen_ai.agent.* attributes in traces
AGENT_AUID=your_agent_auid
# -----------------------------------------------------------------------------
# MCP SERVER CONFIGURATION (ADVANCED)
# -----------------------------------------------------------------------------
# These are typically not needed for standard usage

# Agent ID (required for agentic authentication)
AGENT_ID=your-agent-id
# Local MCP server settings (for custom MCP server development)
MCP_SERVER_PORT=8000
MCP_SERVER_HOST=localhost
MCP_DEVELOPMENT_BASE_URL=

# Agent 365 Agentic Authentication Configuration
# Auth handler name (optional, defaults to "AGENTIC")
# The name of the authentication handler to use for token exchange
AGENT_AUTH_HANDLER_NAME=AGENTIC
# -----------------------------------------------------------------------------
# AGENT 365 APP REGISTRATION (PRODUCTION)
# -----------------------------------------------------------------------------
# Required for production deployments with full authentication
# Get these from Azure Portal > App Registrations > Your App

# Azure AD App Registration
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID=
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET=
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID=
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__SCOPES=https://graph.microsoft.com/.default

# Service URL mapping
CONNECTIONSMAP__0__SERVICEURL=*
CONNECTIONSMAP__0__CONNECTION=SERVICE_CONNECTION

# Optional: Server Configuration
PORT=3978

# Required for observability SDK
ENABLE_OBSERVABILITY=true

ENABLE_A365_OBSERVABILITY_EXPORTER=false

PYTHON_ENVIRONMENT=development
204 changes: 164 additions & 40 deletions python/crewai/sample_agent/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
# CrewAgent Crew - Python
# CrewAI Agent Sample - Python

This sample demonstrates how to build a multiagent system using CrewAI while integrating with the Microsoft Agent 365 SDK. It mirrors the structure and hosting patterns of the AgentFramework/OpenAI Agent 365 samples, while preserving native CrewAI logic in src/crew_agent. It covers:
This sample demonstrates how to build a multi-agent system using CrewAI while integrating with the Microsoft Agent 365 SDK. It mirrors the structure and hosting patterns of the AgentFramework/OpenAI Agent 365 samples, while preserving native CrewAI logic in `src/crew_agent/`.

- **Observability**: End-to-end tracing, caching, and monitoring for agent applications
- **Notifications**: Services and models for managing user notifications
- **Tools**: Model Context Protocol tools for building advanced agent solutions
## Demonstrates

- **MCP Tooling**: Full Model Context Protocol (MCP) integration with Microsoft 365 services (Mail, Calendar, Copilot)
- **Observability**: Complete tracing with `InvokeAgentScope`, `InferenceScope`, and `ExecuteToolScope` for all agent operations
- **Notifications**: Email and Teams @mention notification support
- **Multi-Agent Orchestration**: Sequential agent workflow with Weather Checker and Driving Safety Advisor agents
- **Azure OpenAI Integration**: Native support for Azure OpenAI deployments via CrewAI's `azure-ai-inference` extra and LiteLLM routing
- **Hosting Patterns**: Hosting with Microsoft 365 Agents SDK

This sample uses the [Microsoft Agent 365 SDK for Python](https://github.com/microsoft/Agent365-python).
Expand All @@ -14,56 +18,176 @@ For comprehensive documentation and guidance on building agents with the Microso
## Prerequisites

- Python 3.11+
- Microsoft Agent 365 SDK
- Azure/OpenAI API credentials
- UV (recommended for dependency management)
- [UV](https://docs.astral.sh/uv/) (recommended for dependency management)
- Azure OpenAI API credentials OR OpenAI API key
- [Tavily API key](https://tavily.com) for weather search functionality
- Microsoft 365 Agents Playground (optional, for testing)
- Bearer token from `a365 develop get-token -o raw` (for MCP server authentication)

## Configuration

### Step 1: Create Environment File

Copy `.env.template` to `.env`:

```bash
cp .env.template .env
```

### Step 2: Configure Required Variables

**For Azure OpenAI (recommended):**
```env
AZURE_API_KEY=your-azure-openai-key
AZURE_API_BASE=https://your-resource.openai.azure.com/
AZURE_API_VERSION=2025-01-01-preview
OPENAI_API_KEY=your-azure-openai-key # CrewAI requires this
OPENAI_MODEL_NAME=azure/gpt-4.1 # Use azure/ prefix for LiteLLM
```

**For OpenAI:**
```env
OPENAI_API_KEY=sk-your-openai-key
OPENAI_MODEL_NAME=gpt-4o-mini
```

**For MCP Tools (Mail, Calendar, Copilot):**
```env
BEARER_TOKEN=<run: a365 develop get-token -o raw>
USE_AGENTIC_AUTH=false
AGENTIC_APP_ID=crewai-agent
```

**For Weather Tool:**
```env
TAVILY_API_KEY=tvly-your-tavily-key
```

## Running the Agent

## Customizing
- Add your `OPENAI_API_KEY` into `.env`.
- Modify `src/crew_agent/config/agents.yaml` and `tasks.yaml`.
- Edit `src/crew_agent/crew.py` and `src/crew_agent/main.py` for your logic.
### Option 1: Run via Agent Runner (Standalone)

```bash
uv run python -m crew_agent.agent_runner "London"
# or
uv run agent_runner "San Francisco, CA"
```

### Option 2: Hosted via Generic Agent Host (Recommended)

This option integrates with Microsoft 365 Agents SDK for full observability and MCP tooling.

## Running the Project
1. Ensure `.env` is configured (see above)

### Option 1: Run via Agent Runner
2. Get a bearer token for MCP authentication:
```bash
python -m crew_agent.agent_runner "London"
# or
agent_runner "San Francisco, CA"
a365 develop get-token -o raw
```
Copy the token to `BEARER_TOKEN` in `.env`

3. Start the agent host:
```bash
uv run python start_with_generic_host.py
```

4. Test endpoints:
- Health check: `http://localhost:3978/api/health`
- Bot Framework: `http://localhost:3978/api/messages`

5. Connect with Agents Playground:
```bash
agentsplayground -e "http://localhost:3978/api/messages" -c "emulator"
```

### Example Prompts

```
Find weather in Dublin and email the information to user@example.com under the subject "Weather Report"
```

```
What's the weather in Seattle? Is it safe to drive with summer tires?
```

## Architecture

### Agent Workflow

```
┌─────────────────────────┐ ┌──────────────────────────┐
│ Weather Information │────▶│ Driving Safety │
│ Specialist │ │ Specialist │
│ (Tavily + MCP Tools) │ │ (MCP Tools only) │
└─────────────────────────┘ └──────────────────────────┘
│ │
▼ ▼
Weather Report Safety Assessment + Email
```

### MCP Tools Available

When connected with a valid bearer token, the following MCP servers are available:

| Server | Tools | Description |
|--------|-------|-------------|
| `mcp_MailTools` | 20 tools | Send/receive emails, manage drafts, attachments |
| `mcp_CalendarTools` | 12 tools | Create/manage events, check availability |
| `mcp_M365Copilot` | 1 tool | Query Microsoft 365 Copilot |

### Observability Scopes

All agent operations are traced with Agent 365 observability:

- **InvokeAgentScope**: Wraps the entire agent invocation
- **InferenceScope**: Wraps LLM calls (CrewAI crew execution)
- **ExecuteToolScope**: Wraps each MCP tool execution

## File Structure

```
sample_agent/
├── .env.template # Environment template with documentation
├── start_with_generic_host.py # Main entry point
├── host_agent_server.py # Agent 365 SDK hosting + observability setup
├── agent.py # CrewAI agent wrapper with observability
├── turn_context_utils.py # Turn context utilities
├── ToolingManifest.json # MCP server definitions
└── src/crew_agent/
├── config/
│ ├── agents.yaml # Agent definitions
│ └── tasks.yaml # Task definitions
├── crew.py # CrewAI crew orchestration
└── tools/
└── custom_tool.py # WeatherTool (Tavily)
```

## Troubleshooting

### Common Issues

| Issue | Solution |
|-------|----------|
| `No MCP tools discovered` | Ensure `BEARER_TOKEN` is set and not expired. Run `a365 develop get-token -o raw` |
| `Weather tool returns no data` | Set `TAVILY_API_KEY` in `.env` |
| `Azure OpenAI 401 error` | Verify `AZURE_API_KEY` and `AZURE_API_BASE` are correct |
| `Duplicate emails sent` | Update `tasks.yaml` - only Driving Safety agent should send emails |
| `CrewAI tracing 401` | This is expected when CrewAI cloud tracing is not configured. It can be safely ignored; local observability still works |

### Logs to Check

### Option 2: Hosted via Generic Agent Host with Agent 365 (Microsoft Agent365 SDK)
Mirrors the OpenAI/AgentFramework samples and adds Agent 365 observability + MCP server registration.

1) Copy `.env.template` to `.env` and fill:
- `CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID` / `CLIENTSECRET` / `TENANTID`
- `AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__AGENTIC__SETTINGS__TYPE` / `SCOPES` (already in template)
- `OBSERVABILITY_SERVICE_NAME` / `OBSERVABILITY_SERVICE_NAMESPACE`
- Optional: `BEARER_TOKEN` if you want agentic auth via bearer
2) Run host: `python start_with_generic_host.py`
3) Health: `http://localhost:3978/api/health` (auto-fallback to next port if busy)
4) Playground/Bot Framework endpoint: `http://localhost:3978/api/messages`
- Message text is forwarded into your CrewAI flow as the `location` input.
- MCP servers from the Agent 365 platform are discovered and passed to CrewAI agents (SSE transport with bearer headers).

Agent 365 observability:
- Configured via `microsoft_agents_a365.observability.core.configure` in `agent.py`
- Agentic token is cached/resolved for the exporter (see `token_cache.py`)
- Startup logs show a masked env snapshot

## Understanding Your Crew
1) **Weather Checker**: Uses web search (Tavily) to find current weather conditions
2) **Driving Safety Advisor**: Assesses whether it's safe to drive an MX-5 with summer tires based on weather data
```
INFO:agent:✅ 33 MCP tool(s) available: # MCP connected successfully
INFO:agent:📊 Created observable wrapper # Tool wrappers with ExecuteToolScope
INFO:agent:🔧 Calling MCP tool: SendEmail... # Tool execution
```

## Support

For issues, questions, or feedback:

- **CrewAI Documentation**: https://docs.crewai.com
- **CrewAI GitHub**: https://github.com/joaomdmoura/crewai
- **Microsoft Agent 365 Documentation:**: https://learn.microsoft.com/en-us/microsoft-agent-365/developer/
- **Microsoft Agent 365 Documentation**: https://learn.microsoft.com/en-us/microsoft-agent-365/developer/
- **Discord**: https://discord.com/invite/X4JWnZnxPb

## Contributing
Expand Down
Loading