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
13 changes: 7 additions & 6 deletions Readme-Usage.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Microsoft Agent 365 CLI

A command-line tool for deploying and managing Microsoft Agent 365 applications on Azure.
A command-line tool for deploying and managing Microsoft Agent 365 applications on Azure.

## Supported Platforms
- ✅ .NET Applications
- ✅ Node.js Applications
- ✅ Node.js Applications
- ✅ **Python Applications** (Auto-detects via `pyproject.toml`, handles Microsoft Agent 365 dependencies, converts .env to Azure App Settings)

## Quick Start
Expand Down Expand Up @@ -122,6 +122,7 @@ a365 setup infrastructure
a365 setup blueprint
a365 setup permissions mcp
a365 setup permissions bot
a365 setup permissions copilotstudio # Configure Copilot Studio permissions
```

### Publish & Deploy
Expand Down Expand Up @@ -174,7 +175,7 @@ a365 develop-mcp list-servers -e "Default-12345678-1234-1234-1234-123456789abc"
# Publish an MCP server
a365 develop-mcp publish -e "Default-12345678-1234-1234-1234-123456789abc" -s "msdyn_MyMcpServer"

# Unpublish an MCP server
# Unpublish an MCP server
a365 develop-mcp unpublish -e "Default-12345678-1234-1234-1234-123456789abc" -s "msdyn_MyMcpServer"

# Approve/block MCP servers (global operations, no environment needed)
Expand All @@ -200,14 +201,14 @@ The Agent 365 CLI automatically detects and deploys applications built with:
- **Deployment:** Creates Oryx manifest with `dotnet YourApp.dll` command
- **Requirements:** .NET SDK installed

### Node.js Applications
### Node.js Applications
- **Detection:** Looks for `package.json` file
- **Build Process:** `npm ci` → `npm run build` (if build script exists)
- **Deployment:** Creates Oryx manifest with start script from `package.json`
- **Requirements:** Node.js and npm installed

### Python Applications
- **Detection:** Looks for `requirements.txt`, `setup.py`, `pyproject.toml`, or `*.py` files
- **Detection:** Looks for `requirements.txt`, `setup.py`, `pyproject.toml`, or `*.py` files
- **Build Process:** Copies project files, handles local wheel packages in `dist/`, creates deployment configuration
- **Deployment:** Creates Oryx manifest with appropriate start command (gunicorn, uvicorn, or python)
- **Requirements:** Python 3.11+ and pip installed
Expand All @@ -232,7 +233,7 @@ a365 deploy --dry-run

The CLI automatically:
1. Detects your project platform
2. Validates required tools are installed
2. Validates required tools are installed
3. Cleans previous build artifacts
4. Builds your application using platform-specific tools
5. Creates an appropriate Oryx manifest for Azure App Service
Expand Down
109 changes: 109 additions & 0 deletions docs/commands/setup/setup-permissions-copilotstudio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# a365 setup permissions copilotstudio Command

## Overview

The `a365 setup permissions copilotstudio` command configures OAuth2 permission grants and inheritable permissions for the agent blueprint to invoke Copilot Studio copilots via the Power Platform API.

## Usage

```bash
a365 setup permissions copilotstudio [options]
```

## Options

| Option | Alias | Description | Default |
|--------|-------|-------------|---------|
| `--config` | `-c` | Configuration file path | `a365.config.json` |
| `--verbose` | `-v` | Show detailed output | `false` |
| `--dry-run` | | Show what would be done without making changes | `false` |

## Prerequisites

1. **Blueprint Created**: Run `a365 setup blueprint` first
2. **Global Administrator**: Required for admin consent operations
3. **Azure CLI Authentication**: `az login` with appropriate permissions

## What This Command Does

1. **Ensures Power Platform API Service Principal** exists in your tenant
2. **Creates OAuth2 Permission Grant** from blueprint to Power Platform API
3. **Sets Inheritable Permissions** so agent instances can invoke Copilot Studio

## Permission Configured

| Resource | Scope | Type |
|----------|-------|------|
| Power Platform API (`8578e004-a5c6-46e7-913e-12f58912df43`) | `CopilotStudio.Copilots.Invoke` | Delegated |

## Examples

### Configure CopilotStudio permissions
```bash
a365 setup permissions copilotstudio
```

### Preview changes without executing
```bash
a365 setup permissions copilotstudio --dry-run
```

### Use custom configuration file
```bash
a365 setup permissions copilotstudio --config my-agent.config.json
```

### Show detailed output
```bash
a365 setup permissions copilotstudio --verbose
```

## When to Use This Command

Use this command when your agent needs to:
- Invoke Copilot Studio copilots at runtime
- Call Power Platform APIs that require CopilotStudio permissions

## Related Commands

- `a365 setup blueprint` - Create the agent blueprint (prerequisite)
- `a365 setup permissions mcp` - Configure MCP server permissions
- `a365 setup permissions bot` - Configure Messaging Bot API permissions

## Common Issues

### "Blueprint ID not found" Error
```
ERROR: Blueprint ID not found. Run 'a365 setup blueprint' first.
```
**Solution**: Run `a365 setup blueprint` to create the agent blueprint first.

### Permission Grant Failures
If the command fails during permission grant creation, verify:
- You have Global Administrator permissions
- You're authenticated with `az login`
- The Power Platform API service principal exists in your tenant

## Output Examples

### Successful Execution
```
Configuring CopilotStudio permissions...

✓ Power Platform API service principal found
✓ OAuth2 permission grant created: CopilotStudio.Copilots.Invoke
✓ Inheritable permissions configured

CopilotStudio permissions configured successfully

Your agent blueprint can now invoke Copilot Studio copilots.
```

### Dry Run Output
```
DRY RUN: Configure CopilotStudio Permissions
Would configure Power Platform API permissions:
- Blueprint: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- Resource: Power Platform API (8578e004-a5c6-46e7-913e-12f58912df43)
- Scopes: CopilotStudio.Copilots.Invoke
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Microsoft.Agents.A365.DevTools.Cli.Constants;
using Microsoft.Agents.A365.DevTools.Cli.Helpers;
using Microsoft.Agents.A365.DevTools.Cli.Models;
using Microsoft.Agents.A365.DevTools.Cli.Services;
using Microsoft.Extensions.Logging;
using System.CommandLine;

namespace Microsoft.Agents.A365.DevTools.Cli.Commands.SetupSubcommands;

/// <summary>
/// CopilotStudio permissions subcommand - Configures Power Platform CopilotStudio.Copilots.Invoke permission
/// Required Permissions: Global Administrator (for admin consent)
/// </summary>
internal static class CopilotStudioSubcommand
{
/// <summary>
/// Validates CopilotStudio permissions prerequisites without performing any actions.
/// </summary>
public static Task<List<string>> ValidateAsync(
Agent365Config config,
CancellationToken cancellationToken = default)
{
// Reuse the blueprint validation logic
return ValidationHelper.ValidateBlueprintAsync(config, cancellationToken);
}

public static Command CreateCommand(
ILogger logger,
IConfigService configService,
CommandExecutor executor,
GraphApiService graphApiService,
AgentBlueprintService blueprintService)
{
var command = new Command("copilotstudio",
"Configure Power Platform CopilotStudio.Copilots.Invoke permission\n" +
"Minimum required permissions: Global Administrator\n\n" +
"Prerequisites: Blueprint (run 'a365 setup blueprint' first)");

var configOption = new Option<FileInfo>(
["--config", "-c"],
getDefaultValue: () => new FileInfo("a365.config.json"),
description: "Configuration file path");

var verboseOption = new Option<bool>(
["--verbose", "-v"],
description: "Show detailed output");

var dryRunOption = new Option<bool>(
"--dry-run",
description: "Show what would be done without executing");

command.AddOption(configOption);
command.AddOption(verboseOption);
command.AddOption(dryRunOption);

command.SetHandler(async (config, verbose, dryRun) =>
{
var setupConfig = await configService.LoadAsync(config.FullName);

if (string.IsNullOrWhiteSpace(setupConfig.AgentBlueprintId))
{
logger.LogError("Blueprint ID not found. Run 'a365 setup blueprint' first.");
Environment.Exit(1);
}

// Configure GraphApiService with custom client app ID if available
if (!string.IsNullOrWhiteSpace(setupConfig.ClientAppId))
{
graphApiService.CustomClientAppId = setupConfig.ClientAppId;
}

if (dryRun)
{
logger.LogInformation("DRY RUN: Configure CopilotStudio Permissions");
logger.LogInformation("Would configure Power Platform API permissions:");
logger.LogInformation(" - Blueprint: {BlueprintId}", setupConfig.AgentBlueprintId);
logger.LogInformation(" - Resource: Power Platform API ({ResourceAppId})", MosConstants.PowerPlatformApiResourceAppId);
logger.LogInformation(" - Scopes: CopilotStudio.Copilots.Invoke");
return;
}

await ConfigureAsync(
config.FullName,
logger,
configService,
executor,
setupConfig,
graphApiService,
blueprintService);

}, configOption, verboseOption, dryRunOption);

return command;
}

/// <summary>
/// Configures CopilotStudio permissions (OAuth2 grants and inheritable permissions).
/// Public method that can be called by AllSubcommand.
/// </summary>
public static async Task<bool> ConfigureAsync(
string configPath,
ILogger logger,
IConfigService configService,
CommandExecutor executor,
Models.Agent365Config setupConfig,
GraphApiService graphService,
AgentBlueprintService blueprintService,
SetupResults? setupResults = null,
CancellationToken cancellationToken = default)
{
logger.LogInformation("");
logger.LogInformation("Configuring CopilotStudio permissions...");
logger.LogInformation("");

try
{
// Configure Power Platform API permissions for CopilotStudio
// Note: Power Platform API is a first-party Microsoft service
// We skip addToRequiredResourceAccess because the scopes may not be published there.
await SetupHelpers.EnsureResourcePermissionsAsync(
graphService,
blueprintService,
setupConfig,
MosConstants.PowerPlatformApiResourceAppId,
"Power Platform API (CopilotStudio)",
new[] { MosConstants.PermissionNames.PowerPlatformCopilotStudioInvoke },
logger,
addToRequiredResourceAccess: false,
setInheritablePermissions: true,
setupResults,
cancellationToken);

// write changes to generated config
await configService.SaveStateAsync(setupConfig);

logger.LogInformation("");
logger.LogInformation("CopilotStudio permissions configured successfully");
logger.LogInformation("");
logger.LogInformation("Your agent blueprint can now invoke Copilot Studio copilots.");
return true;
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to configure CopilotStudio permissions: {Message}", ex.Message);
return false;
}
}
}
Loading
Loading