Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
0c6c974
fix: improve non-admin setup flow with self-healing permissions and a…
sellakumaran Mar 16, 2026
76983b1
feat: batch permissions orchestrator for non-admin setup flow
sellakumaran Mar 17, 2026
fa2c0c7
fix: address PR review comments and align setup summary with batch flow
sellakumaran Mar 17, 2026
9aa34a4
fix: use MSAL/WAM as primary Graph token path to fix cross-user conta…
sellakumaran Mar 18, 2026
e80c293
fix: address Copilot PR review comments
sellakumaran Mar 18, 2026
f8c6908
Improve changelog, auth flows, and admin consent handling
sellakumaran Mar 18, 2026
a270a89
fix: correct user identity for ATG and Graph token acquisition
sellakumaran Mar 18, 2026
b5be53e
fix: update test override signature for CreateBrowserCredential login…
sellakumaran Mar 19, 2026
4820d73
fix: address remaining Copilot PR review comments (#2-5)
sellakumaran Mar 19, 2026
40fe88f
fix: resolve Agent ID Admin setup failures for WAM auth, owner assign…
sellakumaran Mar 19, 2026
1576643
Support login hint for MSAL Graph token acquisition
sellakumaran Mar 19, 2026
f37d1aa
fix: pass login hint to blueprint httpClient token to prevent WAM cro…
sellakumaran Mar 19, 2026
80bf137
fix: address Copilot review comments on token cache, log levels, and …
sellakumaran Mar 19, 2026
3b0aa2f
fix: consent URL Graph-only scopes, SP retry, transitiveMemberOf role…
sellakumaran Mar 19, 2026
8027051
chore: remove docs/plans from version control (internal working docum…
sellakumaran Mar 19, 2026
4cc1c30
feat: add a365 setup admin command for Global Administrator OAuth2 gr…
sellakumaran Mar 20, 2026
6a19be9
feat: add consent URL generation, fix SP retry, and improve setup output
sellakumaran Mar 20, 2026
7430bff
Improve admin consent URLs, retry logic, and testability
sellakumaran Mar 20, 2026
960517a
fix: Copilot review comments, GA role detection, combined consent URL…
sellakumaran Mar 20, 2026
3dc1e2e
perf: eliminate real process/network/delay costs in test paths
sellakumaran Mar 21, 2026
a688b6a
Improve auth reliability, logging, and test rigor
sellakumaran Mar 21, 2026
da6f750
perf: eliminate repeated az CLI subprocess spawns across setup phases
sellakumaran Mar 22, 2026
5b05e37
Refactor infra/client validation: direct ARM/Graph HTTP
sellakumaran Mar 22, 2026
9366a5f
Add --field option to config command and standardize endpoint key
sellakumaran Mar 22, 2026
78a70e0
Handle PR comments
sellakumaran Mar 22, 2026
8af956b
Fix PR comments.
sellakumaran Mar 22, 2026
d048465
feat: non-DW blueprint setup and publish flow
sellakumaran Mar 22, 2026
440d401
Add agent instance-only setup and improved cleanup for non-DW
sellakumaran Mar 23, 2026
faf269a
Refactor agent identity flow, improve logging & cleanup
sellakumaran Mar 24, 2026
9764e22
Merge origin/main into users/sellak/nondw
sellakumaran Mar 24, 2026
7181cd5
fix: full permissions for non-DW blueprint flow and correct agent ide…
sellakumaran Mar 25, 2026
37af8b8
Merge remote-tracking branch 'origin/main' into users/sellak/nondw
sellakumaran Mar 25, 2026
d2e0cb1
AgentX V2 registration support and identity flow updates
sellakumaran Mar 26, 2026
0911f90
Unify DW/non-DW setup flows and dynamic permissions
sellakumaran Mar 26, 2026
4a4d752
Merge remote-tracking branch 'origin/main' into users/sellak/nondw
sellakumaran Mar 31, 2026
0e6fed1
fix: improve non-DW setup flow for non-admin developers
sellakumaran Apr 1, 2026
cd6cea1
Grant agent identity permissions & sync observability config
sellakumaran Apr 1, 2026
390abf5
Add AgentBlueprintId to observability config outputs
sellakumaran Apr 1, 2026
8305ec9
fix: polish CLI console output for non-DW blueprint setup flow
sellakumaran Apr 2, 2026
4b8f959
Add config-free setup: --agent-name bootstrap for blueprints
sellakumaran Apr 3, 2026
20bbd35
Merge origin/main into users/sellak/nondw
sellakumaran Apr 4, 2026
67ae2ff
Config-free cleanup, dry-run UX, and auth robustness
sellakumaran Apr 4, 2026
69d6214
Refine non-DW blueprint setup and permissions flow
sellakumaran Apr 4, 2026
4a8ad2b
Improve admin consent handling for Graph/non-Graph APIs
sellakumaran Apr 5, 2026
d70eb86
Add config-free --blueprint-id mode to admin subcommand
sellakumaran Apr 6, 2026
a7e9e03
Support non-admin setup with Principal-scoped grants
sellakumaran Apr 6, 2026
e3913e1
Refactor setup dry-run and summary to numbered steps
sellakumaran Apr 6, 2026
b4a067c
Add Agent 365 VS Code extension with skills & automation
sellakumaran Apr 8, 2026
e95135d
Refactor: update CLI for new Agent ID flow, remove VSCE ext
sellakumaran Apr 9, 2026
a3b34bb
Merge remote-tracking branch 'origin/main' into users/sellak/nondw
sellakumaran Apr 9, 2026
dc5cb36
Simplify agent identity creation to always use delegated flow
sellakumaran Apr 13, 2026
9b12fd7
Refactor non-DW setup: consent UX, testability, fixes
sellakumaran Apr 14, 2026
b53938e
Merge origin/main: adopt S2S app role tracking, AppRoleScopes in specs
sellakumaran Apr 14, 2026
07ec2c0
Update setup instructions with two-question path determination flow
Sunil-Garg Apr 16, 2026
67dc0ed
Switch agent registration from AgentX to Graph API (copilot/agentRegi…
sellakumaran Apr 16, 2026
f809388
Merge origin/main: MCP V1/V2 support, EnableAgent365Exporter flag
sellakumaran Apr 16, 2026
7a22825
Refactor: centralize tenant/app detection & permission specs
sellakumaran Apr 17, 2026
6934616
Merge origin/main: add managerApplications to blueprint creation
sellakumaran Apr 17, 2026
4db8c60
Remove global config directory support; always use local
sellakumaran Apr 17, 2026
021198b
Improve reliability, cancellation, and cleanup robustness
sellakumaran Apr 17, 2026
f431e46
Improve agent identity cleanup and OBO scope handling
sellakumaran Apr 17, 2026
006c232
Clarify agent setup vs observability; improve auth guidance
sellakumaran Apr 17, 2026
228a4ff
Merge branch 'users/sellak/nondw' of https://github.com/microsoft/Age…
Sunil-Garg Apr 17, 2026
352b48e
Update setup flow, config handling, and observability steps
sellakumaran Apr 18, 2026
d5ba176
Refine blueprint logic, fix logging and error messages
sellakumaran Apr 18, 2026
21647ac
Expand observability docs, improve testability and logging
sellakumaran Apr 20, 2026
684dad2
Improve logging, startup, and observability setup UX
sellakumaran Apr 20, 2026
7b31d86
Consolidate config validation to model; update tests/docs
sellakumaran Apr 20, 2026
1c732ab
Ensure ACR names start with letter; allow JSON trailing commas
sellakumaran Apr 20, 2026
bf963b9
refactor: split Question 1 into two-step M365 agent type selection
Sunil-Garg Apr 18, 2026
e4e71d7
refactor: simplify agent type questions to two options with updated c…
Sunil-Garg Apr 19, 2026
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
67 changes: 67 additions & 0 deletions .claude/agents/pr-code-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,73 @@ When a block of code — a method body, a collection initializer, a sequence of

**Real example (from `users/sellak/blueprintScopes`):** `AllSubcommand.cs`, `AdminSubcommand.cs`, and `PermissionsSubcommand.cs` each contained an identical three-entry block for Bot API, Observability API, and Power Platform API. When `Agent365.Observability.OtelWrite` was added, the new scope had to be written in three places — and would have been missed without manual cross-file inspection. Extracted to `SetupHelpers.GetFixedApiPermissionSpecs(bool setInheritable)`.

### 23. Unconditional Success Log After Multiple Fallible Operations

A success or completion log message is emitted unconditionally after a sequence of independent operations that each have their own `if (!ok)` warning branches. The final message claims the whole step succeeded regardless of which individual operations failed.

- **Pattern to catch**:
- A sequence of: `var aOk = await DoA(...); if (!aOk) LogWarning(...); var bOk = await DoB(...); if (!bOk) LogWarning(...); LogInformation("completed successfully");`
- The success log appears at the end without checking `aOk && bOk` — it fires even if every preceding operation returned false
- Common in multi-grant admin consent flows, multi-step provisioning, and batch operations
- **Severity**: `high` — users see "completed successfully" in the terminal while one or more required operations silently failed; they have no indication follow-up action is needed
- **Check**: For every `LogInformation("...success..." or "...completed...")` in the diff, scan backwards to find all `bool`-returning async calls in the same block. Verify each outcome variable is included in a combined guard before the success log.
- **Fix**: Accumulate outcomes and gate the success log:
```csharp
var aOk = await DoA(...);
if (!aOk) logger.LogWarning("A failed.");
var bOk = await DoB(...);
if (!bOk) logger.LogWarning("B failed.");

if (!aOk || !bOk)
{
logger.LogError("Step completed with errors. One or more operations failed and follow-up action is required.");
throw new InvalidOperationException("Step did not complete successfully for all operations.");
}
logger.LogInformation("Step completed successfully.");
```
- **Real example** (`CreateInstanceCommand.cs`): Three separate `CreateOrUpdateOauth2PermissionGrantAsync` calls (MCP scopes, Bot API, Observability API) each had their own `LogWarning` on failure, but a single `LogInformation("Admin consent granted ... completed successfully")` was always emitted at the end. Fixed by computing `adminConsentGrantOk = mcpGrantOk && botApiGrantOk && observabilityApiGrantOk` and throwing if false.

### 24. Expensive Unconditional Startup Code Before Command Dispatch

An HTTP call, token acquisition, subprocess spawn, or other expensive/network-dependent operation runs unconditionally in startup — before `parser.InvokeAsync(args)` and before the user's chosen command is even parsed. This adds latency to every invocation (including `--help`, `--version`, and offline/CI scenarios) and can fail in environments without network access even when the command doesn't require it.

- **Pattern to catch**:
- Any `await SomeService.NetworkCallAsync(...)` in `Program.cs` (or equivalent startup file) between `services.BuildServiceProvider()` and `parser.InvokeAsync(args)`
- Calls to `configService.TryResolveXxx(graphApiService)`, `graphApiService.AnyMethodAsync(...)`, or `AzCliHelper.*` that are NOT inside a command handler lambda
- The call is not guarded by a check of whether the command actually needs the result
- **Severity**: `medium` — noticeable latency on every invocation; breaks offline/CI scenarios; especially bad for interactive developer workflows where `a365 --help` should be instant
- **Fix**: Guard with a check of the args array to skip for informational invocations, or move the call inside the command handlers that actually need it:
```csharp
// Skip for help, version, and empty invocations — must work offline
var isHelpOrVersion = args.Length == 0 || args.Any(a => a is "--help" or "-h" or "--version");
if (!isHelpOrVersion)
{
try { await configService.TryResolveClientAppIdAsync(graphApiService); }
catch (Exception ex) { logger.LogDebug(ex, "Pre-resolution skipped: {Message}", ex.Message); }
}
```
Alternatively, move the call into a `System.CommandLine` middleware so it runs lazily only when a command handler needs it.
- **Real example** (`Program.cs`): `TryResolveClientAppIdAsync` was called unconditionally before `parser.InvokeAsync(args)`, causing a Graph API call + az token acquisition on every invocation including `a365 --help`. Fixed by guarding with `isHelpOrVersion`.

### 25. Validation Rule Change in Model Not Mirrored in Service-Layer Validator

When a required-field check is added, removed, or relaxed in a model's `Validate()` method, the same change is almost always needed in the service-level `ValidateAsync()` method — and vice versa. Failing to update both is the root cause of "fixed in one place but still broken in the other" bugs.

- **Pattern to catch**:
- A diff removes (or adds) a `ValidateRequired(...)` call, or an `if (string.IsNullOrWhiteSpace(...))` guard, inside any `Validate()` method on a model class
- The diff does NOT also touch the service-level validator (`ConfigService.ValidateAsync`, or any method named `ValidateAsync` that takes the same model type)
- **Severity**: `high` — the fix is incomplete; the rule will still fire (or fail to fire) via the other path
- **Check**: For every model-level validation change in the diff, run `Grep` for the same field name + `"is required"` or `ValidateRequired` in `ConfigService.cs`. If the service-level validator has the same rule and the diff doesn't touch it, flag it.
- **Fix**: Apply the same change in both validators, or — better — consolidate so `ConfigService.ValidateAsync` calls `config.Validate()` for required-field rules and only adds format checks on top:
```csharp
// ConfigService.ValidateAsync — required-field rules delegated to the model
var errors = new List<string>(config.Validate());
// Format-only checks follow...
if (!string.IsNullOrWhiteSpace(config.TenantId))
ValidateGuid(config.TenantId, nameof(config.TenantId), errors);
```
- **Real example**: Removing `"messagingEndpoint is required when needDeployment is 'no'."` from `Agent365Config.Validate()` without removing the parallel `ValidateRequired(config.MessagingEndpoint, ...)` call in `ConfigService.ValidateAsync`. The fix appeared in `Agent365ConfigTests.cs` and `Agent365Config.cs` but not in `ConfigService.cs`, so `a365 cleanup` still failed with `MessagingEndpoint is required` on bootstrap-path projects.

## Example Invocation

When you receive a request like "Review PR #253", you should:
Expand Down
1 change: 1 addition & 0 deletions .claude/skills/review-staged/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ The skill analyzes:
- **Security**: Secrets, input validation, error handling
- **Standards**: Coding conventions, file organization
- **Context**: CLI vs GitHub Actions (different standards apply)
- **Full file content**: Every staged file is read in full — not just the changed lines. This catches issues in unchanged sections such as duplicate hardcoded values, parallel code structures that should use a shared helper, or dead code that the diff didn't touch.

## Review Severity Levels

Expand Down
12 changes: 9 additions & 3 deletions .claude/skills/review-staged/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,15 @@ The skill uses **Claude Code directly** for semantic code analysis (same as revi
2. Claude Code reads `.github/copilot-instructions.md` for coding standards
3. Claude Code gets staged files: `git diff --staged --name-only`
4. Claude Code gets staged changes: `git diff --staged`
5. Claude Code performs semantic analysis using its own capabilities
6. Claude Code identifies specific issues with line numbers and code references
7. **Claude Code runs the full test suite with per-test timing:**
5. **Claude Code reads the complete current content of every staged file** (not just diff lines) to enable full-file semantic analysis. This is critical for catching issues that exist in unchanged sections of modified files, such as:
- Duplicate hardcoded constants or magic values that already exist elsewhere
- Parallel code structures that should be consolidated (e.g., a method building the same spec list as a shared helper)
- Unused or dead code that was already there but not touched by the diff
- Missing calls to shared helpers — where the diff adds a new use but existing code still has the old duplicate pattern
For each file path returned in step 3, Claude Code must `Read` the full file before performing analysis.
6. Claude Code performs semantic analysis using its own capabilities
7. Claude Code identifies specific issues with line numbers and code references
8. **Claude Code runs the full test suite with per-test timing:**
```bash
cd src && dotnet test tests.proj --configuration Release --logger "console;verbosity=normal" 2>&1
```
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Internal working documents
docs/plans/
docs/Permissions-Review.md
docs/Testing.md
scripts/skills/

# IDE launch profiles (developer-specific)
**/Properties/launchSettings.json

## A streamlined .gitignore for modern .NET projects
## including temporary files, build results, and
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,19 @@ a365 setup admin --config-dir "<path-to-config-dir>"
- `a365 cleanup azure --dry-run` — preview resources that would be deleted without making any changes or requiring Azure authentication
- `AppServiceAuthRequirementCheck` — validates App Service deployment token before `a365 deploy` begins, catching revoked grants (AADSTS50173) early
- `a365 setup admin` — new command for Global Administrators to complete tenant-wide AllPrincipals OAuth2 permission grants after `a365 setup all` has been run by an Agent ID Admin
- `setup all --agent-name <name>` — config-free non-DW setup. No `a365.config.json` required. TenantId is auto-detected from `az account show`; ClientAppId resolved by finding an Entra app registration named `"Agent 365 CLI"` in the tenant.
- `setup all --tenant-id <id>` — override tenant auto-detection when using `--agent-name`.
- `cleanup --agent-name <name>` — config-free cleanup. No `a365.config.json` required. Loads resource IDs from the global generated config written by bootstrap setup. Tenant ID is auto-detected from `az account show` or overridden with `--tenant-id`.
- MCP V1/V2 migration support — `a365 setup permissions mcp` and `a365 setup blueprint` now handle mixed manifests containing both V1 (`McpServers.*.All` / ATG audience) and V2 (`Tools.ListInvoke.All` / per-server audience) entries; scopes are written additively to the blueprint so agents on either SDK version continue to work
- `--remove-legacy-scopes` flag for `a365 setup permissions mcp` — removes shared ATG audience scopes from the blueprint once V2 SDK is confirmed live across all agents
- `a365 develop get-token` now acquires one token per audience when using manifest-based scope resolution — V2 entries receive a token scoped to their specific server AppId, V1 entries continue to use the shared ATG AppId
- `a365 develop get-token` now writes per-server bearer tokens to `.env` (Python/Node.js) and `launchSettings.json` (.NET) — V2 servers are written as `BEARER_TOKEN_<SERVER_NAME>` (e.g. `BEARER_TOKEN_MCP_WORDSERVER`), V1 shared-audience token continues to be written as `BEARER_TOKEN` for backward compatibility; local dev samples can now run correctly with V2 multi-audience manifests without needing agentic auth
- `a365 setup permissions mcp --remove-legacy-scopes --dry-run` now shows both what would be removed (shared ATG audience entries) and what would remain after removal, instead of only showing what would be configured

### Changed
- `setup all --dry-run` output is now column-aligned for readability
- `setup infrastructure` now defaults `deploymentProjectPath` to the current directory when not specified in config
- `setup all` now defaults to the non-AI Teammate (blueprint) flow. Use `--aiteammate true` to run the Digital Worker (AI Teammate) setup flow.
- `a365 setup blueprint` now sets `managerApplications` on the blueprint application to enable platform manageability. After May 1, blueprints without `managerApplications` will no longer be accepted, and must be recreated (delete and re-run `a365 setup blueprint`) or manually patched via Graph API to include this value.
- `New-Agent365ToolsServicePrincipalProdPublic.ps1` updated to support MCP V1 and V2 provisioning — adds `-Mode` (`V1`/`V2`/`All`, default `All`), `-ManifestPath` (auto-extracts V2 per-server AppIds from `ToolingManifest.json`), and `-V2AppIds` (explicit list) parameters; script is now idempotent across all AppIds (re-run safe) and covers the migration period where V1 and V2 servers coexist in the same tenant
- `a365 publish` updates manifest IDs, creates `manifest.zip`, and prints concise upload instructions for Microsoft 365 Admin Center (Agents > All agents > Upload custom agent). Interactive prompts only occur in interactive terminals; redirect stdin to suppress them in scripts.
Expand All @@ -64,6 +70,7 @@ a365 setup admin --config-dir "<path-to-config-dir>"
- macOS/Linux: device code fallback when browser authentication is unavailable (#309)
- Linux: MSAL fallback when PowerShell `Connect-MgGraph` fails in non-TTY environments (#309)
- Admin consent polling no longer times out after 180s — blueprint service principal now resolved with correct MSAL token (#309)
- `a365 cleanup --agent-name` no longer stalls — interactive browser auth failure in embedded terminals now automatically falls back to device code flow (same as Conditional Access fallback)
- `ConfigFileNotFoundException` now derives from `FileNotFoundException` so existing catch sites continue to work (#309)
- `a365 develop list-available` no longer displays `Required Scope: null` for servers that return a `"null"` string scope from the V2 catalog endpoint
- `a365 develop add-mcp-servers` no longer writes the literal string `"null"` as a scope value in `ToolingManifest.json` when the V2 catalog returns `"scope": "null"` — the field is omitted, allowing correct fallback to name-based scope mapping
Expand Down
48 changes: 48 additions & 0 deletions docs/agent365-guided-setup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Agent 365 Guided Setup — Index

> **If you are a coding agent (Claude Code, GitHub Copilot, Devin, or similar):**
> Read this file first, identify the task below, then **immediately open and follow ONLY the linked instruction file**. Open **one file only** — do NOT read both instruction files. Do NOT explore the codebase, fetch web pages, or run commands until you have read the instruction file. The instruction file is your complete guide.

---

## Which file do I need?

### "Make my agent A365 compliant" / "Set up my agent for Agent 365" / "Run agent setup"

**→ Open and follow: [a365-setup-instructions.md](a365-setup-instructions.md)**

Use this file when the user asks to:
- Make an agent A365 compliant
- Set up, provision, or configure an agent for Agent 365
- Run `a365 setup` or provision Azure / Entra resources
- Deploy an agent application

### "Add observability to my agent" / "Set up logging / telemetry / tracing"

**→ Open and follow: [a365-observability-instructions.md](a365-observability-instructions.md)**

Use this file when the user asks to:
- Add observability, telemetry, logging, or tracing to their agent
- Integrate OpenTelemetry or the Agent 365 observability stack
- Monitor agent activity or usage

---

## If the intent is unclear

If the user's request matches more than one category, or you are unsure, ask:

> "Are you looking to (1) set up your agent for Agent 365 compliance, or (2) add observability/telemetry to an existing agent?"

Wait for the answer, then open the appropriate file above.

---

## What NOT to do

- Do NOT open both instruction files. Open the one file that matches the task and follow it exclusively.
- Do NOT treat "make my agent A365 compliant" as including observability. Setup and observability are separate tasks with separate instruction files.
- Do NOT glob, search, or read files in the broader repository before reading the instruction file.
- Do NOT fetch external URLs or documentation before reading the instruction file.
- Do NOT ask clarifying questions beyond the one above if the intent is clear.
- Do NOT start writing code or running commands until the instruction file tells you to.
Loading
Loading