Skip to content

re-enable create instance#347

Open
gwharris7 wants to merge 13 commits intomainfrom
users/gwharris7/create-instance
Open

re-enable create instance#347
gwharris7 wants to merge 13 commits intomainfrom
users/gwharris7/create-instance

Conversation

@gwharris7
Copy link
Copy Markdown
Contributor

@gwharris7 gwharris7 commented Apr 2, 2026

This pull request re-enables the a365 create-instance command, 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 #274

Command Reactivation and Modernization

  • Re-enabled the a365 create-instance command, updating its description and restoring its subcommands (identity, licenses) for standard use instead of deprecation. [1] [2] [3]
  • Updated the implementation to use dependency-injected GraphApiService throughout the command and its subcommands, removing legacy authentication and service instantiation logic. [1] [2] [3] [4] [5] [6] [7]

Sponsor Handling and Error Reporting

  • Made sponsor (current user) mandatory for agent identity creation, removing the previous fallback that retried without a sponsor and caused BadRequest errors; added clear error messages and recommended actions if the sponsor cannot be determined. [1] [2] [3] [4]

Licensing Updates

  • Updated the license assignment logic to use the new Microsoft_Agent_365_Tier_3 SKU instead of the previous Teams and E5 SKUs, and updated related log messages. [1] [2] [3]

Deprecation Removal and Documentation

  • Removed deprecation error logging and related unreachable code from the command and runner, reflecting the command's restored status. [1] [2] [3]

Changelog and User Guidance

  • Updated CHANGELOG.md to reflect the re-enabled command, sponsor requirement, and improved error handling. [1] [2]

Test Matrix

Agent ID Developer Agent ID Administrator
create instance creates identity and agent user from config
[subcommand] create identity with no licenses
[subcommand] add licenses to existing user
chat with agent in Teams

Copilot AI review requested due to automatic review settings April 2, 2026 19:56
@gwharris7 gwharris7 requested review from a team as code owners April 2, 2026 19:56
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA c15f928.
Ensure 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 Files

None

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-instance subcommands (identity, licenses) and removes deprecation behavior.
  • Updates A365CreateInstanceRunner to require a sponsor and uses the Microsoft_Agent_365_Tier_3 SKU.
  • 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.Content more than once (ReadAsStringAsync earlier, then again here). HttpContent isn’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);

@sellakumaran
Copy link
Copy Markdown
Contributor

Can you add the manual end to end test matrix that was verified to the PR please?

@sellakumaran
Copy link
Copy Markdown
Contributor

Do we need admin consent step?
In theory, since blueprint has inheritance set and admin has already consented on blueprint, we should not require this step.

Can you verify please?

@gwharris7
Copy link
Copy Markdown
Contributor Author

Do we need admin consent step? In theory, since blueprint has inheritance set and admin has already consented on blueprint, we should not require this 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).

@gwharris7
Copy link
Copy Markdown
Contributor Author

Can you add the manual end to end test matrix that was verified to the PR please?

Agent ID Developer Agent ID Administrator
create instance creates identity and agent user from config
[subcommand] create identity with no licenses
[subcommand] add licenses to existing user
chat with agent in Teams

Copilot AI review requested due to automatic review settings April 4, 2026 00:11
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 IBotConfigurator isn’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);

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 4, 2026 00:22
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

  • --verbose is 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 the cleanLoggerFactory (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;
            }

Copilot AI review requested due to automatic review settings April 4, 2026 01:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Copilot AI review requested due to automatic review settings April 4, 2026 02:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Comment on lines 99 to +103
| `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 |
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copilot uses AI. Check for mistakes.
```

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.
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
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");
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
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");

Copilot uses AI. Check for mistakes.
Comment on lines 497 to 501
// 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
{
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +460 to 463
// Get current user for sponsor (REQUIRED by Graph API)
string? currentUserId = null;
try
{
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +131 to +137
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,
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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,

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable create-instance command

3 participants