Conversation
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Snapshot WarningsEnsure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice. Scanned FilesNone |
There was a problem hiding this comment.
Pull request overview
Re-enables the a365 create-instance workflow and updates it to align with current Graph API requirements (notably sponsor-required agent identity creation) and updated licensing, while modernizing command wiring to use dependency-injected services.
Changes:
- Restores
create-instancesubcommands (identity,licenses) and removes deprecation behavior. - Updates
A365CreateInstanceRunnerto require a sponsor and uses theMicrosoft_Agent_365_Tier_3SKU. - Updates tests and changelog to reflect the command reactivation.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/Microsoft.Agents.A365.DevTools.Cli/Commands/CreateInstanceCommand.cs | Re-enables command + subcommands and switches runner to DI-provided GraphApiService. |
| src/Microsoft.Agents.A365.DevTools.Cli/Services/A365CreateInstanceRunner.cs | Enforces sponsor requirement and updates license assignment SKU/log output. |
| src/Tests/Microsoft.Agents.A365.DevTools.Cli.Tests/Commands/CreateInstanceCommandTests.cs | Updates expectations to match command no longer being deprecated. |
| CHANGELOG.md | Documents command re-enable and sponsor-handling fix. |
Comments suppressed due to low confidence (1)
src/Microsoft.Agents.A365.DevTools.Cli/Services/A365CreateInstanceRunner.cs:539
- The failure path reads
identityResponse.Contentmore than once (ReadAsStringAsyncearlier, then again here).HttpContentisn’t guaranteed to be readable multiple times; read the error body once and reuse it for all checks/logs.
if (!identityResponse.IsSuccessStatusCode)
{
var errorContent = await identityResponse.Content.ReadAsStringAsync(ct);
_logger.LogError("Failed to create agent identity: {Status} - {Error}", identityResponse.StatusCode, errorContent);
return (false, null);
src/Microsoft.Agents.A365.DevTools.Cli/Services/A365CreateInstanceRunner.cs
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Services/A365CreateInstanceRunner.cs
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Commands/CreateInstanceCommand.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Commands/CreateInstanceCommand.cs
Outdated
Show resolved
Hide resolved
|
Can you add the manual end to end test matrix that was verified to the PR please? |
|
Do we need admin consent step? Can you verify please? |
@sellakumaran Admin consent is not required. Consent inheritance is enabled by default. If consent inheritance is not enabled for some reason, the command attempts to apply the required scopes directly to the agent identity (which requires admin privileges). |
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (2)
src/Microsoft.Agents.A365.DevTools.Cli/Commands/CreateInstanceCommand.cs:61
- The dry-run output claims a Step 3 "Configure Bot Service", but this handler doesn’t appear to perform any bot configuration (and
IBotConfiguratorisn’t used). Either update the user-facing step text to reflect the actual actions performed, or implement the missing bot configuration step so the output is accurate.
logger.LogInformation("DRY RUN: Agent 365 Instance Creation - All Steps");
logger.LogInformation("This would execute the following operations:");
logger.LogInformation(" 1. Create Agent Identity and Agent User");
logger.LogInformation(" 2. Add licenses to Agent User");
logger.LogInformation(" 3. Configure Bot Service");
logger.LogInformation("No actual changes will be made.");
src/Microsoft.Agents.A365.DevTools.Cli/Services/A365CreateInstanceRunner.cs:539
identityResponse.Content.ReadAsStringAsync()is invoked more than once in this error-handling path. Consider reading the content once into a local variable and reusing it to avoid redundant reads and keep the flow easier to follow.
if (!identityResponse.IsSuccessStatusCode)
{
var errorContent = await identityResponse.Content.ReadAsStringAsync(ct);
_logger.LogError("Failed to create agent identity: {Status} - {Error}", identityResponse.StatusCode, errorContent);
return (false, null);
src/Microsoft.Agents.A365.DevTools.Cli/Commands/CreateInstanceCommand.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
src/Microsoft.Agents.A365.DevTools.Cli/Commands/CreateInstanceCommand.cs:412
--verboseis accepted by the licenses subcommand handler but never used, so it currently has no effect. Consider using it to control the minimum log level of thecleanLoggerFactory(and any debug logging), or remove the option to avoid advertising unsupported behavior.
command.AddOption(configOption);
command.AddOption(verboseOption);
command.AddOption(dryRunOption);
command.SetHandler(async (config, verbose, dryRun) =>
{
if (dryRun)
{
logger.LogInformation("DRY RUN: Adding licenses to Agent User");
logger.LogInformation("This would assign M365 and Power Platform licenses to the agent user");
return;
}
src/Microsoft.Agents.A365.DevTools.Cli/Commands/CreateInstanceCommand.cs
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Commands/CreateInstanceCommand.cs
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Services/A365CreateInstanceRunner.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Commands/CreateInstanceCommand.cs
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Services/A365CreateInstanceRunner.cs
Show resolved
Hide resolved
src/Microsoft.Agents.A365.DevTools.Cli/Constants/AuthenticationConstants.cs
Show resolved
Hide resolved
| | `AgentIdentityBlueprint.UpdateAuthProperties.All` | Update Blueprint auth properties | | ||
| | `Application.ReadWrite.All` | Create and manage Azure AD applications | | ||
| | `DelegatedPermissionGrant.ReadWrite.All` | Grant delegated permissions | | ||
| | `Directory.Read.All` | Read directory data | | ||
| | `User.ReadWrite.All` | Create agent users, set usage location, and assign licenses | |
There was a problem hiding this comment.
The permission list/count here doesn’t match what the CLI enforces. AuthenticationConstants.RequiredClientAppPermissions includes AgentIdentityBlueprint.AddRemoveCreds.All in addition to the six listed here, so users following this guide may still fail validation. Update the table and the stated count to include AddRemoveCreds.All (and reflect 7 total).
| ``` | ||
|
|
||
| From the output of the command above, verify these 5 permissions appear with admin consent. If any are missing or consent is not granted, see "What to do if validation fails" below. | ||
| From the output of the command above, verify these 6 permissions appear with admin consent. If any are missing or consent is not granted, see "What to do if validation fails" below. |
There was a problem hiding this comment.
This guide still states earlier that create-instance is deprecated in favor of publish, but this PR re-enables create-instance. Please update that earlier guidance so the setup instructions don’t contradict the current CLI behavior.
| logger.LogInformation("DRY RUN: Agent 365 Instance Creation - All Steps"); | ||
| logger.LogInformation("This would execute the following operations:"); | ||
| logger.LogInformation(" 1. Create Agent Identity and Agent User"); | ||
| logger.LogInformation(" 2. Add licenses to Agent User"); |
There was a problem hiding this comment.
The --dry-run output lists only identity creation and license assignment, but the command also performs MCP/permission grant work and Graph agent registration later in the handler. Consider updating the dry-run description so it accurately reflects the operations that would run (or clarify which steps are excluded).
| logger.LogInformation(" 2. Add licenses to Agent User"); | |
| logger.LogInformation(" 2. Add licenses to Agent User"); | |
| logger.LogInformation(" 3. Configure MCP and grant required permissions"); | |
| logger.LogInformation(" 4. Register the agent with Microsoft Graph"); |
| // Create agent identity via service principal endpoint | ||
| var createIdentityUrl = $"{GraphApiConstants.BaseUrl}/beta/serviceprincipals/Microsoft.Graph.AgentIdentity"; | ||
| var graphBaseUrl = _graphService.GraphBaseUrl; | ||
| var createIdentityUrl = $"{graphBaseUrl}/beta/serviceprincipals/Microsoft.Graph.AgentIdentity"; | ||
| var identityBody = new JsonObject | ||
| { |
There was a problem hiding this comment.
GraphBaseUrl is used for the AgentIdentity creation endpoint below, but other Graph-specific values in this workflow are still hard-coded to GraphApiConstants.BaseUrl: (1) the sponsor lookup calls "{GraphApiConstants.BaseUrl}/v1.0/me" earlier in this method, and (2) GetBlueprintAccessTokenAsync builds the client-credentials scope as "{GraphApiConstants.BaseUrl}/.default". In sovereign clouds, those commercial-cloud constants can break the flow even if GraphBaseUrl is overridden; use the configured base URL consistently for both HTTP endpoints and OAuth resource scopes.
| // Get current user for sponsor (REQUIRED by Graph API) | ||
| string? currentUserId = null; | ||
| try | ||
| { |
There was a problem hiding this comment.
The comment block in this section refers to using an Azure CLI token to call /me, but the code now uses GraphApiService.GetGraphAccessTokenAsync (MSAL-based) for delegated auth. Please update the nearby comment(s) to reflect the actual auth flow so troubleshooting guidance isn’t misleading.
| var Agent365ToolsResourceSpObjectId = await graphApiService.LookupServicePrincipalByAppIdAsync(instanceConfig.TenantId, resourceAppId) | ||
| ?? throw new InvalidOperationException("Agent 365 Tools Service Principal not found for appId " + resourceAppId); | ||
|
|
||
| var response = await graphApiService.CreateOrUpdateOauth2PermissionGrantAsync( | ||
| instanceConfig.TenantId, | ||
| agenticAppSpObjectId, | ||
| Agent365ToolsResourceSpObjectId, |
There was a problem hiding this comment.
Local variable name Agent365ToolsResourceSpObjectId is PascalCase, which is inconsistent with other locals in this method (camelCase) and typical C# conventions. Rename it to camelCase (e.g., agent365ToolsResourceSpObjectId) for consistency/readability.
| var Agent365ToolsResourceSpObjectId = await graphApiService.LookupServicePrincipalByAppIdAsync(instanceConfig.TenantId, resourceAppId) | |
| ?? throw new InvalidOperationException("Agent 365 Tools Service Principal not found for appId " + resourceAppId); | |
| var response = await graphApiService.CreateOrUpdateOauth2PermissionGrantAsync( | |
| instanceConfig.TenantId, | |
| agenticAppSpObjectId, | |
| Agent365ToolsResourceSpObjectId, | |
| var agent365ToolsResourceSpObjectId = await graphApiService.LookupServicePrincipalByAppIdAsync(instanceConfig.TenantId, resourceAppId) | |
| ?? throw new InvalidOperationException("Agent 365 Tools Service Principal not found for appId " + resourceAppId); | |
| var response = await graphApiService.CreateOrUpdateOauth2PermissionGrantAsync( | |
| instanceConfig.TenantId, | |
| agenticAppSpObjectId, | |
| agent365ToolsResourceSpObjectId, |
This pull request re-enables the
a365 create-instancecommand, updating it to align with current Microsoft Graph API requirements and product licensing. The command and its subcommands are no longer deprecated and now require a sponsor for agent identity creation. The implementation has been modernized to use dependency-injected services and the correct license SKU. Error handling and user guidance have also been improved. This resolves #274Command Reactivation and Modernization
a365 create-instancecommand, updating its description and restoring its subcommands (identity,licenses) for standard use instead of deprecation. [1] [2] [3]GraphApiServicethroughout the command and its subcommands, removing legacy authentication and service instantiation logic. [1] [2] [3] [4] [5] [6] [7]Sponsor Handling and Error Reporting
BadRequesterrors; added clear error messages and recommended actions if the sponsor cannot be determined. [1] [2] [3] [4]Licensing Updates
Microsoft_Agent_365_Tier_3SKU instead of the previous Teams and E5 SKUs, and updated related log messages. [1] [2] [3]Deprecation Removal and Documentation
Changelog and User Guidance
CHANGELOG.mdto reflect the re-enabled command, sponsor requirement, and improved error handling. [1] [2]Test Matrix