Skip to content

A dynamic, plugin-based multi-agent system built on Microsoft's Agent Framework with automatic tool and agent discovery. Create powerful AI agents with just YAML configuration files - no code required!

Notifications You must be signed in to change notification settings

alilibx/ms-agentic-framework-accelerator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

20 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Microsoft's Agent Framework Accelerator

A dynamic, plugin-based multi-agent system built on Microsoft's Agent Framework with automatic tool and agent discovery. Create powerful AI agents with just YAML configuration files - minimal code!

Python 3.11+ License: MIT

🎯 Why This Framework?

Before vs After: The Transformation

❌ Traditional Microsoft Agent Framework

# 1️⃣ Manually create tools
from azure.ai.projects.agentic import FunctionTool

def weather_tool():
    """Hard-coded tool definition"""
    pass

weather = FunctionTool(weather_tool, ...)

# 2️⃣ Manually register in __init__.py
from .weather import weather_tool
from .stock import stock_tool
# ... repeat for every tool

# 3️⃣ Hard-code agent configuration
agent = ChatAgent(
    name="Weather Agent",
    instructions="Long prompt...",
    tools=[weather, forecast, ...]  # Manual list
)

# 4️⃣ Edit Python for every change
# Want to add a tool? Edit 3+ files
# Want to change prompt? Edit Python
# Want new agent? Write more Python

Pain Points:

  • πŸ”΄ 20-30 lines per tool setup
  • πŸ”΄ Edit 3+ files per tool
  • πŸ”΄ Manual import management
  • πŸ”΄ Hard-coded configurations
  • πŸ”΄ Code changes for prompts
  • πŸ”΄ Complex maintenance

βœ… This Accelerator Framework

# 1️⃣ Drop a tool file - auto-discovered!
# tools/weather/humidity.py
@tool(domain="weather", description="...")
def get_humidity(location: str) -> str:
    return f"Humidity: 65%"

# Done! ✨ Automatically registered

# 2️⃣ Drop a YAML file - instant agent!
# agents/weather_agent.yaml
name: "Weather Assistant"
tool_domains: ["weather"]
instructions: |
  You are a weather assistant...

# Done! ✨ Automatically created

# 3️⃣ Launch DevUI
python run_devui.py
# All agents & tools auto-discovered! πŸš€

Benefits:

  • βœ… 5 lines per tool
  • βœ… Drop file & done
  • βœ… Zero imports needed
  • βœ… YAML configuration
  • βœ… Edit prompts in YAML
  • βœ… Effortless scaling

πŸ“Š Impact Comparison

Metric Before After Improvement
Lines of Code per Tool 20-30 5-8 75% reduction
Files to Edit per Agent 3-5 1 80% reduction
Time to Add Tool 15-20 min 2-3 min 85% faster
Time to Add Agent 30-45 min 5 min 90% faster
Manual Imports Every tool Zero 100% automated
Configuration Changes Edit Python Edit YAML Non-technical friendly

🎬 Workflow Comparison

Traditional Approach:
─────────────────────────────────────────────────────────────────
Create tool.py β†’ Edit __init__.py β†’ Import in agent.py β†’
Create agent class β†’ Register agent β†’ Test β†’ Debug imports β†’
Restart β†’ Test again
⏱️  Time: ~45 minutes per agent

This Framework:
─────────────────────────────────────────────────────────────────
Drop tool.py β†’ Drop agent.yaml β†’ Run DevUI
⏱️  Time: ~5 minutes per agent

πŸš€ 10x faster development

🌟 Features

Dynamic Tool Discovery

  • Zero-Code Tool Integration: Drop a Python file in tools/domain/ and it's automatically available
  • Decorator-Based Registration: Simple @tool decorator handles all registration
  • Domain Organization: Tools organized by business domain (weather, stock, email, calendar)
  • Tag-Based Filtering: Fine-grained control over which tools each agent gets
  • Hot-Reload Support: Modify tools without restarting the system

Automatic Agent Discovery

  • YAML-Based Configuration: Define agents declaratively without writing Python
  • Zero-Code Agent Creation: Drop a YAML file in agents/ and it's immediately available
  • Automatic Tool Attachment: Agents automatically discover and attach tools based on domains/tags
  • No Manual Registration: No need to edit __init__.py or import statements

Microsoft Agent Framework Integration

  • Sequential Workflows: Chain agents in sequence for complex workflows
  • Parallel Execution: Run multiple agents concurrently with fan-out/fan-in patterns
  • Custom Aggregators: Combine parallel results with custom logic
  • Multi-Provider LLM Support: Azure OpenAI, OpenRouter, and direct OpenAI with automatic fallback

Developer Experience

  • DevUI Integration: Built-in web interface for testing and debugging
  • Comprehensive Logging: Detailed logs for tool discovery and agent creation
  • Mock & Real APIs: Easy toggle between mock data and real API integrations
  • Gmail Integration: Full OAuth2 support for real email operations
  • OpenRouter Support: Access to 100+ LLM models through a single API
  • Type Safety: Full type hints and annotations throughout

πŸ“‹ Table of Contents

πŸš€ Quick Start

Prerequisites

  • Python 3.11 or higher
  • One of the following LLM providers:
    • Azure OpenAI (with Azure CLI)
    • OpenRouter API key (Get one here)
    • Direct OpenAI API key
  • Optional:
    • Gmail account (for real email features)
    • Google Cloud project (for Gmail API)

Installation

  1. Clone the repository
git clone https://github.com/yourusername/agentic-ms.git
cd agentic-ms
  1. Create virtual environment
python -m venv .venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate
  1. Install dependencies
pip install -r requirements.txt
  1. Configure environment
# Copy example environment file
cp .env.example .env

# Edit with your API keys and configuration
nano .env  # or use your preferred editor

Choose your LLM provider (edit .env):

  • Option A: OpenRouter (Easiest for testing)

    OPENROUTER_API_KEY=sk-or-v1-your-key-here
    OPENROUTER_MODEL=openai/gpt-4-turbo
  • Option B: Azure OpenAI

    az login  # Authenticate Azure CLI
    AZURE_OPENAI_ENDPOINT=https://your-endpoint.openai.azure.com/
    AZURE_OPENAI_DEPLOYMENT=gpt-4o
  • Option C: Direct OpenAI

    OPENAI_API_KEY=sk-your-key-here
    OPENAI_MODEL=gpt-4-turbo-preview
  1. Optional: Enable Gmail Integration

See Setup Guide - Gmail Section for detailed instructions.

Quick setup:

USE_REAL_EMAIL_API=true
GMAIL_CREDENTIALS_FILE=credentials.json
GMAIL_USER_EMAIL=your.email@gmail.com
  1. Run the DevUI
# Using bun (recommended)
bun run agent

# Or using Python directly
python run_devui.py

Open http://localhost:8080 in your browser and start chatting with agents!

πŸš€ New to the project? Check out the Quick Start Guide (5 min setup!)

πŸ“š For detailed setup instructions, see the Complete Setup Guide

πŸ“ Project Structure

agentic-ms/
β”œβ”€β”€ agents/                      # Agent YAML configurations
β”‚   β”œβ”€β”€ agent_factory.py        # Factory for creating agents from YAML
β”‚   β”œβ”€β”€ __init__.py             # Auto-discovery of all agents
β”‚   β”œβ”€β”€ weather_agent.yaml      # Weather assistant configuration
β”‚   β”œβ”€β”€ stock_agent.yaml        # Stock market assistant configuration
β”‚   β”œβ”€β”€ email_agent.yaml        # Email assistant configuration
β”‚   β”œβ”€β”€ calendar_agent.yaml     # Calendar assistant configuration
β”‚   └── general_openrouter_agent.yaml  # OpenRouter-powered agent (NEW)
β”‚
β”œβ”€β”€ tools/                       # Tool library (auto-discovered)
β”‚   β”œβ”€β”€ _decorators.py          # @tool decorator for registration
β”‚   β”œβ”€β”€ _registry.py            # Central tool registry (singleton)
β”‚   β”œβ”€β”€ _loader.py              # Auto-discovery engine
β”‚   β”œβ”€β”€ __init__.py             # Package initialization
β”‚   β”‚
β”‚   β”œβ”€β”€ weather/                # Weather domain tools
β”‚   β”‚   β”œβ”€β”€ current_weather.py
β”‚   β”‚   └── forecast.py
β”‚   β”‚
β”‚   β”œβ”€β”€ stock/                  # Stock market domain tools
β”‚   β”‚   β”œβ”€β”€ stock_price.py
β”‚   β”‚   β”œβ”€β”€ stock_analysis.py
β”‚   β”‚   └── stock_history.py
β”‚   β”‚
β”‚   β”œβ”€β”€ email/                  # Email domain tools
β”‚   β”‚   β”œβ”€β”€ send_email.py
β”‚   β”‚   β”œβ”€β”€ read_inbox.py
β”‚   β”‚   β”œβ”€β”€ search_emails.py
β”‚   β”‚   └── gmail_utils.py      # Gmail API integration (NEW)
β”‚   β”‚
β”‚   β”œβ”€β”€ calendar/               # Calendar domain tools
β”‚   β”‚   β”œβ”€β”€ create_event.py
β”‚   β”‚   β”œβ”€β”€ list_events.py
β”‚   β”‚   └── find_free_time.py
β”‚   β”‚
β”‚   └── common/                 # Shared utility tools
β”‚
β”œβ”€β”€ workflows/                   # Workflow orchestrations
β”‚   β”œβ”€β”€ financial_workflow.py  # Sequential workflow example
β”‚   └── reusable_workflows.py  # Parallel workflow examples
β”‚
β”œβ”€β”€ docs/                        # Documentation
β”‚   β”œβ”€β”€ DYNAMIC_TOOL_ARCHITECTURE.md
β”‚   β”œβ”€β”€ AGENT_WORKFLOW_ARCHITECTURE.md
β”‚   β”œβ”€β”€ PARALLEL_EXECUTION_QUICKSTART.md
β”‚   β”œβ”€β”€ SETUP_GUIDE.md          # Complete setup guide (NEW)
β”‚   └── EMAIL_AGENT_DEMO.md
β”‚
β”œβ”€β”€ demos/                       # Demo scripts
β”‚   β”œβ”€β”€ demo_parallel_execution.py
β”‚   └── workflow_runner.py
β”‚
β”œβ”€β”€ run_devui.py                # Launch DevUI with all agents
β”œβ”€β”€ test_agent_factory.py       # Test YAML-based agents
β”œβ”€β”€ test_auto_discovery.py      # Test automatic discovery
└── requirements.txt            # Python dependencies

πŸ’‘ Core Concepts

1. Tools

Tools are Python functions decorated with @tool that provide specific capabilities to agents.

Key Features:

  • Automatic discovery via filesystem scanning
  • Domain-based organization (weather, stock, email, etc.)
  • Tag-based filtering for fine-grained control
  • Mock vs real API support

2. Agents

Agents are AI assistants configured via YAML files that automatically discover and use tools.

Key Features:

  • Declarative YAML configuration
  • Automatic tool attachment based on domains/tags
  • Editable prompts without code changes
  • Azure OpenAI integration

3. Workflows

Workflows orchestrate multiple agents to solve complex tasks.

Types:

  • Sequential: Agents run one after another
  • Parallel: Agents run concurrently (fan-out/fan-in)
  • Custom: Build complex routing and conditional logic

πŸ›  Creating Tools

Step 1: Create a Tool File

Create a Python file in the appropriate domain folder:

# tools/weather/humidity.py
from typing import Annotated
from tools._decorators import tool

@tool(
    domain="weather",
    description="Get humidity levels for a location",
    tags=["weather", "humidity", "conditions"],
    mock=True,  # Set to False when using real APIs
)
def get_humidity(
    location: Annotated[str, "The location to check humidity for"]
) -> str:
    """Get humidity percentage for a given location.

    Args:
        location: City name or location string

    Returns:
        Formatted string with humidity information
    """
    # Mock implementation
    return f"Humidity in {location}: 65%"

Step 2: That's It!

The tool is now:

  • βœ… Automatically discovered at startup
  • βœ… Registered in the tool registry
  • βœ… Available to all agents with tool_domains: ["weather"]

No code editing, imports, or registration needed!

Tool Decorator Parameters

@tool(
    domain: str,              # Required: Tool domain (weather, stock, email, etc.)
    name: Optional[str],      # Optional: Tool name (defaults to function name)
    description: Optional[str], # Optional: Description (defaults to docstring)
    tags: Optional[list],     # Optional: Additional tags for filtering
    mock: bool = False,       # Optional: Is this a mock implementation?
    requires_api_key: Optional[str], # Optional: API key environment variable
)

πŸ€– Creating Agents

Step 1: Create a YAML Configuration

Create a YAML file in the agents/ directory:

# agents/news_agent.yaml
name: "News Assistant"
description: "Provides latest news headlines and articles"

# Tool Discovery - automatically finds matching tools
tool_domains:
  - news

tool_tags:
  - news
  - headlines
  - articles

# Optional: Exclude specific tools
# exclude_tools:
#   - news.experimental_feature

# Agent Instructions (the "prompt")
instructions: |
  You are a news assistant. Provide latest news headlines
  and articles when asked. Always cite your sources and
  present information objectively.

  When users ask about news:
  1. Use the appropriate tool to fetch articles
  2. Summarize key points clearly
  3. Provide source attribution

# Model Configuration - Multi-Provider with Automatic Fallback
model:
  # Provider list (will try in order until one succeeds)
  providers:
    - "openrouter"  # Try OpenRouter first (easiest, no auth issues)
    - "azure"       # Fall back to Azure if available
    - "openai"      # Fall back to OpenAI if available

  # Azure configuration (used if azure provider succeeds)
  endpoint: "https://your-azure-openai.openai.azure.com/"
  deployment: "gpt-4o"
  credential_type: "azure_cli"

  # OpenRouter/OpenAI config loaded from environment:
  # OPENROUTER_API_KEY, OPENROUTER_MODEL, OPENAI_API_KEY

Step 2: Create Domain Tools (if needed)

If the domain doesn't exist, create tools for it:

# tools/news/get_headlines.py
from tools._decorators import tool

@tool(domain="news", description="Get latest news headlines")
def get_headlines(category: str = "general") -> str:
    """Fetch latest news headlines."""
    # Implementation here
    return "Latest headlines..."

Step 3: Restart and Use!

python run_devui.py

The news agent is now automatically:

  • βœ… Discovered from the YAML file
  • βœ… Created with matching tools attached
  • βœ… Available in the DevUI

No Python code editing required!

πŸƒ Running the System

DevUI (Web Interface)

Launch the development web interface:

python run_devui.py

Features:

  • Chat with individual agents
  • Test workflows
  • View agent capabilities
  • Debug tool calls

Python API

Use agents programmatically:

from agents import get_all_agents
import asyncio

async def main():
    # Get all auto-discovered agents
    agents = get_all_agents()

    # Use weather agent
    weather_agent = agents['weather_agent']
    response = await weather_agent.run("What's the weather in Tokyo?")
    print(response)

asyncio.run(main())

Testing

Run the test suites:

# Test tool discovery
python -c "from tools import ToolRegistry; print(ToolRegistry().get_summary())"

# Test agent creation
python test_agent_factory.py

# Test automatic discovery
python test_auto_discovery.py

πŸ“š Examples

Example 1: Simple Agent Query

from agents import get_all_agents
import asyncio

async def main():
    agents = get_all_agents()
    weather_agent = agents['weather_agent']

    response = await weather_agent.run(
        "What's the weather forecast for Seattle this week?"
    )
    print(response)

asyncio.run(main())

Example 2: Sequential Workflow

from agent_framework import SequentialBuilder
from agents import get_all_agents

agents = get_all_agents()
stock_agent = agents['stock_agent']
weather_agent = agents['weather_agent']

workflow = (
    SequentialBuilder()
    .add_agent(stock_agent)
    .add_agent(weather_agent)
    .build()
)

# Execute: stock analysis β†’ weather check
result = await workflow.run("Analyze AAPL and check weather in Cupertino")

Example 3: Parallel Workflow

from agent_framework import ConcurrentBuilder
from agents import get_all_agents

agents = get_all_agents()

workflow = (
    ConcurrentBuilder()
    .participants([agents['stock_agent'], agents['weather_agent']])
    .build()
)

# Both agents run simultaneously
result = await workflow.run("Get AAPL price and Seattle weather")

Example 4: Creating a Custom Tool

# tools/news/search_articles.py
from typing import Annotated
from tools._decorators import tool

@tool(
    domain="news",
    description="Search news articles by keyword",
    tags=["news", "search", "articles"],
    mock=True
)
def search_articles(
    query: Annotated[str, "Search query"],
    days: Annotated[int, "Days to look back"] = 7
) -> str:
    """Search for news articles matching the query."""
    return f"Found 10 articles about '{query}' from last {days} days"

πŸ— Architecture

Complete Framework Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                 MS-AGENTIC FRAMEWORK ACCELERATOR                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                      AGENT LAYER (YAML)                      β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚   β”‚
β”‚  β”‚  β”‚ Weather Agentβ”‚  β”‚Calendar Agentβ”‚  β”‚  Stock Agent β”‚        β”‚   β”‚
β”‚  β”‚  β”‚   .yaml      β”‚  β”‚    .yaml     β”‚  β”‚    .yaml     β”‚        β”‚   β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚   β”‚ 
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚            β”‚                  β”‚                  β”‚                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚              AGENT FACTORY (Dynamic Discovery)               β”‚   β”‚
β”‚  β”‚  β€’ YAML Parser      β€’ Tool Discovery Integration             β”‚   β”‚ 
β”‚  β”‚  β€’ Chat Client      β€’ Multi-Provider Fallback                β”‚   β”‚
β”‚  β”‚  β€’ Context Injector β€’ Azure/OpenRouter/OpenAI Support        β”‚   β”‚ 
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚            β”‚                                                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚            TOOL REGISTRY & DISCOVERY ENGINE                  β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚   β”‚
β”‚  β”‚  β”‚         Automatic Tool Discovery                   β”‚      β”‚   β”‚
β”‚  β”‚  β”‚  β€’ Recursive directory scanning                    β”‚      β”‚   β”‚
β”‚  β”‚  β”‚  β€’ @tool decorator detection                       β”‚      β”‚   β”‚
β”‚  β”‚  β”‚  β€’ Metadata extraction                             β”‚      β”‚   β”‚
β”‚  β”‚  β”‚  β€’ Dynamic registration                            β”‚      β”‚   β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚   β”‚
β”‚  β”‚                                                              β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚   β”‚
β”‚  β”‚  β”‚         Tool Registry (Singleton)                  β”‚      β”‚   β”‚
β”‚  β”‚  β”‚  β€’ Domain filtering (weather, calendar, stock)     β”‚      β”‚   β”‚
β”‚  β”‚  β”‚  β€’ Tag filtering (forecast, event, price)          β”‚      β”‚   β”‚
β”‚  β”‚  β”‚  β€’ Metadata storage (docs, params, types)          β”‚      β”‚   β”‚
β”‚  β”‚  β”‚  β€’ Hot-reload support                              β”‚      β”‚   β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                             β”‚                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚              TOOL DOMAINS (4 Active Domains)                 β”‚   β”‚
β”‚  β”‚                                                              β”‚   β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚   β”‚
β”‚  β”‚  β”‚  WEATHER   β”‚  β”‚  CALENDAR  β”‚  β”‚  STOCK  β”‚  β”‚  EMAIL   β”‚   β”‚   β”‚
β”‚  β”‚  β”‚  Domain    β”‚  β”‚  Domain    β”‚  β”‚ Domain  β”‚  β”‚  Domain  β”‚   β”‚   β”‚
β”‚  β”‚  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€   β”‚   β”‚
β”‚  β”‚  β”‚ current_   β”‚  β”‚ create_    β”‚  β”‚ stock_  β”‚  β”‚ send_    β”‚   β”‚   β”‚
β”‚  β”‚  β”‚ weather    β”‚  β”‚ event      β”‚  β”‚ price   β”‚  β”‚ email    β”‚   β”‚   β”‚
β”‚  β”‚  β”‚            β”‚  β”‚            β”‚  β”‚         β”‚  β”‚          β”‚   β”‚   β”‚
β”‚  β”‚  β”‚ forecast   β”‚  β”‚ list_      β”‚  β”‚ stock_  β”‚  β”‚ read_    β”‚   β”‚   β”‚
β”‚  β”‚  β”‚            β”‚  β”‚ events     β”‚  β”‚ analysisβ”‚  β”‚ inbox    β”‚   β”‚   β”‚
β”‚  β”‚  β”‚            β”‚  β”‚            β”‚  β”‚         β”‚  β”‚          β”‚   β”‚   β”‚
β”‚  β”‚  β”‚            β”‚  β”‚ delete_    β”‚  β”‚ stock_  β”‚  β”‚ search_  β”‚   β”‚   β”‚
β”‚  β”‚  β”‚            β”‚  β”‚ event      β”‚  β”‚ history β”‚  β”‚ emails   β”‚   β”‚   β”‚
β”‚  β”‚  β”‚            β”‚  β”‚            β”‚  β”‚         β”‚  β”‚          β”‚   β”‚   β”‚
β”‚  β”‚  β”‚            β”‚  β”‚ find_free_ β”‚  β”‚         β”‚  β”‚ organize β”‚   β”‚   β”‚
β”‚  β”‚  β”‚            β”‚  β”‚ time       β”‚  β”‚         β”‚  β”‚ _email   β”‚   β”‚   β”‚
β”‚  β”‚  β”‚            β”‚  β”‚            β”‚  β”‚         β”‚  β”‚          β”‚   β”‚   β”‚
β”‚  β”‚  β”‚ (2 tools)  β”‚  β”‚ (4 tools)  β”‚  β”‚(3 tools)β”‚  β”‚ (4 tools)β”‚   β”‚   β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                             β”‚                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚                 DEVUI & ORCHESTRATION                        β”‚   β”‚
β”‚  β”‚  β€’ Web-based UI for agent interaction                        β”‚   β”‚
β”‚  β”‚  β€’ Real-time tool discovery display                          β”‚   β”‚
β”‚  β”‚  β€’ Auto-startup agent loading                                β”‚   β”‚
β”‚  β”‚  β€’ Sequential & parallel workflow execution                  β”‚   β”‚
β”‚  β”‚  β€’ Live execution monitoring                                 β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Dynamic Tool Discovery Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    START: run_devui.py                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  ToolLoader.discover_tools()        β”‚
        β”‚  β€’ Scans tools/ directory           β”‚
        β”‚  β€’ Recursively walks subdirectories β”‚
        β”‚  β€’ Finds all .py files              β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                β”‚             β”‚             β”‚
                β–Ό             β–Ό             β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ tools/       β”‚  β”‚ tools/       β”‚  β”‚ tools/       β”‚
    β”‚ weather/     β”‚  β”‚ calendar/    β”‚  β”‚ stock/       β”‚
    β”‚              β”‚  β”‚              β”‚  β”‚              β”‚
    β”‚ current_     β”‚  β”‚ create_      β”‚  β”‚ stock_       β”‚
    β”‚ weather.py   β”‚  β”‚ event.py     β”‚  β”‚ price.py     β”‚
    β”‚              β”‚  β”‚              β”‚  β”‚              β”‚
    β”‚ forecast.py  β”‚  β”‚ list_        β”‚  β”‚ stock_       β”‚
    β”‚              β”‚  β”‚ events.py    β”‚  β”‚ analysis.py  β”‚
    β”‚              β”‚  β”‚              β”‚  β”‚              β”‚
    β”‚              β”‚  β”‚ delete_      β”‚  β”‚ stock_       β”‚
    β”‚              β”‚  β”‚ event.py     β”‚  β”‚ history.py   β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                β”‚             β”‚             β”‚
                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  For each file:                     β”‚
        β”‚  β€’ Import module dynamically        β”‚
        β”‚  β€’ Find @tool decorated functions   β”‚
        β”‚  β€’ Extract metadata                 β”‚
        β”‚  β€’ Register in ToolRegistry         β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  ToolRegistry (Singleton)           β”‚
        β”‚  _tools = {                         β”‚
        β”‚    "weather.current_weather": {...},β”‚
        β”‚    "calendar.create_event": {...},  β”‚
        β”‚    "stock.stock_price": {...},      β”‚
        β”‚    ...                              β”‚
        β”‚  }                                  β”‚
        β”‚                                     β”‚
        β”‚  βœ“ 11+ tools registered             β”‚
        β”‚  βœ“ 4 domains active                 β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Agent Discovery & Creation Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         AgentFactory.discover_all_agents()                     β”‚
β”‚         β€’ Scans agents/ directory for *.yaml files             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚                                         β”‚
         β–Ό                                         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  weather_agent.yaml      β”‚         β”‚  stock_agent.yaml        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚         β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚  β”‚ 1. Load YAML config  β”‚β”‚         β”‚  β”‚ 1. Load YAML config  β”‚β”‚
β”‚  β”‚                      β”‚β”‚         β”‚  β”‚                      β”‚β”‚
β”‚  β”‚ 2. Parse domains:    β”‚β”‚         β”‚  β”‚ 2. Parse domains:    β”‚β”‚
β”‚  β”‚    [weather]         β”‚β”‚         β”‚  β”‚    [stock, weather]  β”‚β”‚
β”‚  β”‚                      β”‚β”‚         β”‚  β”‚                      β”‚β”‚
β”‚  β”‚ 3. Query registry:   β”‚β”‚         β”‚  β”‚ 3. Query registry:   β”‚β”‚
β”‚  β”‚    get_tools_by_     β”‚β”‚         β”‚  β”‚    get_tools_by_     β”‚β”‚
β”‚  β”‚    domain("weather") β”‚β”‚         β”‚  β”‚    domain("stock")   β”‚β”‚
β”‚  β”‚                      β”‚β”‚         β”‚  β”‚                      β”‚β”‚
β”‚  β”‚ 4. Results:          β”‚β”‚         β”‚  β”‚ 4. Results:          β”‚β”‚
β”‚  β”‚    [current_weather, β”‚β”‚         β”‚  β”‚    [stock_price,     β”‚β”‚
β”‚  β”‚     forecast]        β”‚β”‚         β”‚  β”‚     stock_analysis,  β”‚β”‚
β”‚  β”‚                      β”‚β”‚         β”‚  β”‚     stock_history] + β”‚β”‚
β”‚  β”‚ 5. Build client:     β”‚β”‚         β”‚  β”‚    [current_weather] β”‚β”‚
β”‚  β”‚    Try providers:    β”‚β”‚         β”‚  β”‚                      β”‚β”‚
β”‚  β”‚    - OpenRouter βœ“    β”‚β”‚         β”‚  β”‚ 5. Build client:     β”‚β”‚
β”‚  β”‚                      β”‚β”‚         β”‚  β”‚    Try providers:    β”‚β”‚
β”‚  β”‚ 6. Inject context:   β”‚β”‚         β”‚  β”‚    - OpenRouter βœ“    β”‚β”‚
β”‚  β”‚    Add tool docs to  β”‚β”‚         β”‚  β”‚                      β”‚β”‚
β”‚  β”‚    instructions      β”‚β”‚         β”‚  β”‚ 6. Inject context    β”‚β”‚
β”‚  β”‚                      β”‚β”‚         β”‚  β”‚                      β”‚β”‚
β”‚  β”‚ 7. Create ChatAgent  β”‚β”‚         β”‚  β”‚ 7. Create ChatAgent  β”‚β”‚
β”‚  β”‚    βœ“ Ready!          β”‚β”‚         β”‚  β”‚    βœ“ Ready!          β”‚β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚         β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚ All agents loaded:               β”‚
           β”‚ {                                β”‚
           β”‚   'weather_agent': <ChatAgent>,  β”‚
           β”‚   'calendar_agent': <ChatAgent>, β”‚
           β”‚   'stock_agent': <ChatAgent>,    β”‚
           β”‚   'email_agent': <ChatAgent>     β”‚
           β”‚ }                                β”‚
           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚ StartupLogger displays:          β”‚
           β”‚ β€’ Tools discovered by domain     β”‚
           β”‚ β€’ Agents created                 β”‚
           β”‚ β€’ Agent β†’ Tool mappings          β”‚
           β”‚ β€’ Model provider info            β”‚
           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
           β”‚ DevUI Server Launch              β”‚
           β”‚ serve(entities=agents)           β”‚
           β”‚ β†’ http://localhost:8080          β”‚
           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Multi-Provider Fallback System

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Agent YAML Configuration                                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ model:                                             β”‚  β”‚
β”‚  β”‚   providers:           ← Try in order             β”‚  β”‚
β”‚  β”‚     - "openrouter"     ← 1st: Easy, no auth       β”‚  β”‚
β”‚  β”‚     - "azure"          ← 2nd: Enterprise          β”‚  β”‚
β”‚  β”‚     - "openai"         ← 3rd: Direct API          β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚               β”‚               β”‚
              β–Ό               β–Ό               β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚OpenRouterβ”‚    β”‚  Azure   β”‚    β”‚ OpenAI   β”‚
        β”‚  Client  β”‚    β”‚ OAI Clientβ”‚   β”‚  Client  β”‚
        β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
              β”‚               β”‚               β”‚
              β”‚  Try connect  β”‚               β”‚
    Success? ─┼─ YES ──┐      β”‚               β”‚
              β”‚        β”‚      β”‚               β”‚
              β”‚  NO ───┼──────┼─ Try Azure    β”‚
              β”‚        β”‚      β”‚               β”‚
              β”‚        β”‚ Success? ───┐        β”‚
              β”‚        β”‚      β”‚      β”‚        β”‚
              β”‚        β”‚  NO ─┼──────┼── Try OpenAI
              β”‚        β”‚      β”‚      β”‚        β”‚
              β”‚        β”‚      β”‚   Success? ────
              β”‚        β”‚      β”‚               β”‚
              β–Ό        β–Ό      β–Ό               β–Ό
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  Return working client to AgentFactory   β”‚
        β”‚  β€’ Zero config changes needed            β”‚
        β”‚  β€’ Automatic failover                    β”‚
        β”‚  β€’ Production-ready reliability          β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Complete Data Flow

User launches application
        β”‚
        β–Ό
    run_devui.py
        β”‚
        β”œβ”€β–Ί Load environment (.env)
        β”‚
        β”œβ”€β–Ί Import agents package
        β”‚   β”‚
        β”‚   └─► agents/__init__.py
        β”‚       β”‚
        β”‚       β”œβ”€β–Ί AgentFactory()
        β”‚       β”‚
        β”‚       └─► discover_all_agents()
        β”‚           β”‚
        β”‚           β”œβ”€β–Ί Scan agents/*.yaml
        β”‚           β”‚
        β”‚           └─► For each YAML:
        β”‚               β”‚
        β”‚               β”œβ”€β–Ί Parse config
        β”‚               β”‚
        β”‚               β”œβ”€β–Ί Query ToolRegistry
        β”‚               β”‚   └─► get_tools_by_domain()
        β”‚               β”‚
        β”‚               β”œβ”€β–Ί Build chat client
        β”‚               β”‚   └─► Try providers
        β”‚               β”‚
        β”‚               β”œβ”€β–Ί Inject tool context
        β”‚               β”‚   └─► Enhance instructions
        β”‚               β”‚
        β”‚               └─► Create ChatAgent
        β”‚
        β”œβ”€β–Ί Get discovery data
        β”‚   └─► {agents, tools_by_domain, mappings}
        β”‚
        β”œβ”€β–Ί Print startup summary
        β”‚   └─► Beautiful CLI output
        β”‚
        └─► Start DevUI server
            └─► serve() β†’ http://localhost:8080
                β”‚
                └─► Browser auto-opens
                    β”‚
                    └─► User interacts with agents
                        β”‚
                        └─► Agents use tools dynamically

Tool Registry Operations

The ToolRegistry maintains a central registry of all discovered tools with powerful query capabilities:

Core Operations:

  • get_tools_by_domain(domain) - Filter by domain (weather, calendar, etc.)
  • get_tools_by_tags(tags) - Filter by tags (forecast, event, etc.)
  • get_tool(tool_id) - Get specific tool by ID
  • list_domains() - Get all available domains
  • get_summary() - Get registry statistics

Example:

from tools import ToolRegistry

registry = ToolRegistry()

# Get all weather tools
weather_tools = registry.get_tools_by_domain("weather")
# Returns: [current_weather, forecast]

# Get all tools tagged with "event"
event_tools = registry.get_tools_by_tags(["event"])
# Returns: [create_event, delete_event, list_events]

# Get summary
summary = registry.get_summary()
# {
#   'total_tools': 11,
#   'domains': ['weather', 'calendar', 'stock', 'email'],
#   'tools_by_domain': {...}
# }

βš™οΈ Configuration

Multi-Provider Support with Automatic Fallback

All agents now support automatic provider fallback - if one provider fails (e.g., Azure auth issues), the system automatically tries the next provider in the list.

How it works:

  1. Agent YAML specifies a list of providers to try
  2. System attempts each provider in order
  3. First successful provider is used
  4. If all fail, error is reported

Example configuration:

model:
  providers:
    - "openrouter"  # Try first (easiest, no Azure auth needed)
    - "azure"       # Try second (if Azure CLI is authenticated)
    - "openai"      # Try third (if OpenAI API key is set)

Benefits:

  • βœ… No more agent failures due to Azure auth issues
  • βœ… Seamless switching between providers
  • βœ… Development-friendly (OpenRouter) with production Azure support
  • βœ… Zero code changes needed

Supported Providers:

  • OpenRouter: Access 100+ models via single API key
  • Azure OpenAI: Enterprise-grade Azure integration
  • OpenAI: Direct OpenAI API access

Agent Configuration (YAML)

name: "Agent Name"                    # Required: Display name
description: "Agent description"      # Required: Short description

tool_domains:                         # Optional: Domain filters
  - domain1
  - domain2

tool_tags:                            # Optional: Tag filters
  - tag1
  - tag2

exclude_tools:                        # Optional: Tools to exclude
  - tool.name

instructions: |                       # Required: Agent prompt
  Your instructions here...

# Model Configuration - Multi-Provider Support
model:
  # Provider list (tries in order until one succeeds)
  providers:                          # Required: List of providers to try
    - "openrouter"                    # Recommended first choice
    - "azure"                         # Fallback to Azure
    - "openai"                        # Fallback to OpenAI

  # Azure OpenAI configuration
  endpoint: "https://..."             # Azure OpenAI endpoint
  deployment: "model-name"            # Deployment name
  credential_type: "azure_cli"        # azure_cli or api_key

  # OpenRouter/OpenAI config (from environment)
  # OPENROUTER_API_KEY, OPENROUTER_MODEL
  # OPENAI_API_KEY, OPENAI_MODEL

Environment Variables

Create a .env file for API keys:

# ============================================================================
# LLM Provider Configuration (choose one or all for automatic fallback)
# ============================================================================

# OpenRouter (Recommended for development - easiest setup)
OPENROUTER_API_KEY=sk-or-v1-your-key-here
OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
OPENROUTER_MODEL=openai/gpt-4o-mini
OPENROUTER_APP_NAME=your-app-name

# Azure OpenAI (Enterprise production use)
AZURE_OPENAI_ENDPOINT=https://your-endpoint.openai.azure.com/
AZURE_OPENAI_DEPLOYMENT=gpt-4o
AZURE_OPENAI_API_VERSION=2024-02-15-preview
# Note: Also requires `az login` for azure_cli authentication

# Direct OpenAI (Alternative to Azure)
OPENAI_API_KEY=sk-your-key-here
OPENAI_MODEL=gpt-4-turbo-preview

# ============================================================================
# Optional: Real API keys for tools
# ============================================================================
OPENWEATHER_API_KEY=your_key_here
ALPHA_VANTAGE_API_KEY=your_key_here

# ============================================================================
# Gmail Integration (Optional)
# ============================================================================
USE_REAL_EMAIL_API=true
GMAIL_CREDENTIALS_FILE=credentials.json
GMAIL_TOKEN_FILE=token.json
GMAIL_USER_EMAIL=your.email@gmail.com

Tool Configuration

@tool(
    domain="your_domain",           # Required
    name="tool_name",               # Optional
    description="What it does",    # Optional
    tags=["tag1", "tag2"],         # Optional
    mock=True,                     # Use mock data (True/False)
    requires_api_key="API_KEY_ENV" # Environment variable name
)

🀝 Contributing

We welcome contributions! Here's how to get started:

Setting Up Development Environment

  1. Fork the repository
  2. Clone your fork
  3. Create a virtual environment
  4. Install dependencies: pip install -r requirements.txt
  5. Create a branch: git checkout -b feature/your-feature

Adding a New Domain

  1. Create domain folder: mkdir tools/your_domain
  2. Add __init__.py: touch tools/your_domain/__init__.py
  3. Create tools: Add Python files with @tool decorators
  4. Create agent YAML: Add agents/your_domain_agent.yaml
  5. Test: Run python test_auto_discovery.py
  6. Submit PR: Create a pull request with your changes

Code Style

  • Follow PEP 8 guidelines
  • Use type hints for all functions
  • Add docstrings to all public functions
  • Use meaningful variable names
  • Keep functions focused and small

Testing

Before submitting a PR:

# Test tool discovery
python -c "from tools import ToolRegistry; ToolRegistry().get_summary()"

# Test agent creation
python test_agent_factory.py

# Test your new domain
python test_auto_discovery.py

Pull Request Process

  1. Update documentation for new features
  2. Add examples if adding new capabilities
  3. Ensure all tests pass
  4. Update README if needed
  5. Describe changes in PR description

πŸ“– Documentation

Comprehensive documentation available in the docs/ folder:

πŸ› Troubleshooting

Tools Not Discovered

Problem: Tools not showing up in registry

Solution:

  1. Check file is in tools/domain/ directory
  2. Ensure @tool decorator is present
  3. Verify __init__.py exists in domain folder
  4. Check logs for import errors

Agent Not Created

Problem: Agent YAML file not creating agent

Solution:

  1. Verify YAML syntax is correct
  2. Check domain names match tool domains
  3. Ensure Azure OpenAI credentials are configured
  4. Check logs for errors during discovery

Connection Errors

Problem: Azure OpenAI connection fails

Solution:

  1. Verify endpoint URL is correct (must include .azure.com)
  2. Check Azure CLI is authenticated: az account show
  3. Verify deployment name matches your Azure setup
  4. Check network connectivity

πŸ€– Available Agents

The system includes 4 pre-built agents with 11 tools across 4 domains:

🌀️ Weather Assistant

  • Tools: 2 (current weather, forecast)
  • Use Cases: Weather forecasts, current conditions
  • Example: "What's the weather in Tokyo?"

πŸ“ˆ Stock Market Assistant

  • Tools: 3 (price, analysis, history)
  • Use Cases: Stock prices, analyst ratings, historical data
  • Example: "Analyze AAPL stock"

πŸ“§ Email Assistant

  • Tools: 3 (send, read inbox, search)
  • Use Cases: Email management, inbox checking
  • Example: "Show me my unread emails"

πŸ“… Calendar Assistant

  • Tools: 3 (create event, list events, find free time)
  • Use Cases: Schedule management, availability checking
  • Example: "Find me a free slot tomorrow afternoon"

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • Microsoft Agent Framework: Core agent orchestration framework
  • Azure OpenAI: LLM infrastructure
  • Contributors: Thanks to all contributors who help improve this project

πŸ“§ Contact

πŸ—ΊοΈ Roadmap

Current Version (v1.0)

  • βœ… Dynamic tool discovery
  • βœ… Automatic agent discovery
  • βœ… YAML-based configuration
  • βœ… Sequential workflows
  • βœ… Parallel workflows
  • βœ… DevUI integration

Planned Features (v2.0)

  • πŸ”„ MCP Server implementation
  • πŸ”„ Real API integrations (OpenWeatherMap, Alpha Vantage)
  • πŸ”„ Tool versioning system
  • πŸ”„ Agent performance monitoring
  • πŸ”„ Hot-reload without restart
  • πŸ”„ Plugin marketplace

Future Enhancements

  • Multiple LLM provider support (OpenAI, Anthropic, etc.)
  • Tool dependency management
  • Conditional workflow routing
  • Agent-to-agent communication
  • Distributed agent execution
  • Web-based agent configuration UI

Made with ❀️ using Microsoft Agent Framework

Star ⭐ this repo if you find it useful!

About

A dynamic, plugin-based multi-agent system built on Microsoft's Agent Framework with automatic tool and agent discovery. Create powerful AI agents with just YAML configuration files - no code required!

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •