This document provides a high-level overview of the Microsoft Agent 365 DevTools repository architecture, design patterns, and architectural decisions.
For development how-to guides (build, test, add commands, etc.), see DEVELOPER.md.
The Microsoft Agent 365 CLI (a365) is a .NET 8.0 tool that automates the deployment and management of Microsoft Agent 365 applications on Azure. It provides:
- Multiplatform deployment (.NET, Node.js, Python) with automatic platform detection
- Agent blueprint and identity creation via Microsoft Graph API
- Messaging endpoint registration with Azure Bot Service
- Application deployment with Azure Oryx manifest generation
- Microsoft Graph API permissions and admin consent management
- Teams notifications registration
- MCP (Model Context Protocol) server configuration and management
Agent365-devTools/
├── src/
│ ├── Microsoft.Agents.A365.DevTools.Cli/ # Main CLI application
│ ├── Microsoft.Agents.A365.DevTools.MockToolingServer/ # Mock MCP server for testing
│ └── Tests/ # Test projects
├── docs/
│ ├── design.md # This file - architecture overview
│ └── commands/ # Command-specific documentation
├── scripts/ # Build and utility scripts
└── CLAUDE.md # Claude Code guidance
flowchart TB
subgraph CLI["a365 CLI"]
Commands["Commands<br/>(config, setup, deploy, etc.)"]
Services["Services<br/>(ConfigService, DeploymentService, etc.)"]
Builders["Platform Builders<br/>(DotNet, Node, Python)"]
end
subgraph External["External Services"]
Azure["Azure Resource Manager<br/>(App Service, Web Apps)"]
Graph["Microsoft Graph API<br/>(Entra ID, Permissions)"]
Bot["Azure Bot Service<br/>(Messaging Endpoints)"]
M365["Microsoft 365 Admin Center<br/>(Agent Upload)"]
Dataverse["Dataverse<br/>(MCP Server Management)"]
end
subgraph Config["Configuration"]
StaticConfig["a365.config.json<br/>(User-managed)"]
DynamicConfig["a365.generated.config.json<br/>(CLI-managed)"]
end
Commands --> Services
Services --> Builders
Services --> Azure
Services --> Graph
Services --> Bot
Services --> M365
Services --> Dataverse
Services --> Config
| Project | Description | Design Document |
|---|---|---|
| Microsoft.Agents.A365.DevTools.Cli | Main CLI application with commands, services, and platform builders | CLI Design |
| Microsoft.Agents.A365.DevTools.MockToolingServer | Mock MCP server for local development and testing | MockToolingServer Design |
| Tests | Unit and integration tests | See DEVELOPER.md |
Commands inherit from AsyncCommand<Settings> and return integer exit codes (0 = success). Each command has:
- A nested
Settingsclass for command-line options - An
ExecuteAsyncmethod containing the implementation - Dependencies injected via constructor
public class SetupCommand : AsyncCommand<SetupCommand.Settings>
{
public class Settings : CommandSettings
{
[CommandOption("--config")]
public string? ConfigFile { get; init; }
}
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings)
{
// Implementation
return 0; // Success
}
}The IPlatformBuilder interface enables multiplatform deployment support:
public interface IPlatformBuilder
{
Task<bool> ValidateEnvironmentAsync();
Task CleanAsync(string projectDir);
Task<string> BuildAsync(string projectDir, string outputPath, bool verbose);
Task<OryxManifest> CreateManifestAsync(string projectDir, string publishPath);
}Implementations: DotNetBuilder, NodeBuilder, PythonBuilder
Configuration is split into two files to separate user concerns from runtime state:
| File | Purpose | Version Control |
|---|---|---|
a365.config.json |
Static, user-managed settings (tenant ID, resource names) | Yes (no secrets) |
a365.generated.config.json |
Dynamic, CLI-managed state (IDs, timestamps) | No (gitignored) |
Both files are merged into a single Agent365Config model at runtime using ConfigService.
Services are registered in Program.cs using Microsoft.Extensions.DependencyInjection:
- Singletons for stateless services
- Transient for command-specific services
- Constructor injection throughout
Problem: Multiple config files (setup.config.json, createinstance.config.json, deploy.config.json) led to:
- Data duplication and inconsistency
- Manual merging required
- Type mismatches and errors
Solution: Single Agent365Config model with:
- Clear static (
init) vs dynamic (get; set) semantics - Automatic merge/split via
ConfigService - Type safety across all commands
- Single source of truth
Design Goals:
- User config can be version controlled (without secrets)
- Generated state is gitignored (contains IDs and secrets)
- Clear ownership: users edit their config, CLI manages state
Why not one file? Separating concerns prevents accidental secret commits and makes config sharing easier.
Why not three+ files? Previous approach caused duplication and cognitive overhead.
Selected for:
- Rich, colorful console output
- Progress indicators and spinners
- Table formatting for status displays
- Robust command-line parsing
- Active development and community support
The CLI leverages Azure CLI for:
- Existing authentication session reuse
- Proven Azure operations
- Cross-platform compatibility
- Reduced maintenance burden
Added: February 2026
The CLI now supports configuring custom API permissions for agent blueprints beyond the standard set required for agent operation. This enables agents to access additional Microsoft Graph scopes (Presence, Files, Chat, etc.) or custom APIs.
Key Components:
- Configuration Model:
CustomResourcePermissionwith GUID validation, scope validation, and duplicate detection - Configuration Command:
a365 config permissionsto add/update/reset custom permissions ina365.config.json - Setup Commands:
a365 setup permissions customand integration witha365 setup all - Storage: Custom permissions stored in
a365.config.json(static configuration)
Architecture:
User configures → a365.config.json → Setup applies → OAuth2 grants + Inheritable permissions
Usage:
# Configure custom permissions
a365 config permissions \
--resource-app-id 00000003-0000-0000-c000-000000000000 \
--scopes Presence.ReadWrite,Files.Read.All
# Apply to blueprint
a365 setup permissions custom
# Or use setup all (auto-applies if configured)
a365 setup allDesign Highlights:
- Generic: Supports Microsoft Graph, custom APIs, and first-party services
- Idempotent: Safe to run multiple times
- Validated: GUID format, scope presence, duplicate detection
- Integrated: Uses same
SetupHelpers.EnsureResourcePermissionsAsyncas standard permissions - Portal Visible: Permissions appear in Azure Portal API permissions list
Documentation:
- Design: design-custom-resource-permissions.md
- Command Reference: a365 setup permissions custom
- GitHub Issue: #194
- CLI Design - Detailed CLI architecture, folder structure, configuration system
- MockToolingServer Design - Mock MCP server architecture
- Developer Guide - Build, test, contribute, add commands
- CLAUDE.md - Claude Code guidance for this repository
- CLI Usage Guide - End-user documentation
- Command Documentation - Index of CLI commands and links to Microsoft Learn reference
- Code Standards - Coding conventions and review rules