Refine Agent 365 SDK identity naming and scoping - #615
Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Renames the Agent 365 SDK-facing identity surface from AgenticIdentity to AgentUser, updating the Core/Apps/BotBuilder layers, samples, docs, and tests while intentionally preserving legacy wire-contract JSON field names and lifecycle value/event identifiers for Teams interoperability.
Changes:
- Replace
AgenticIdentitywithAgentUseracross request-context plumbing (BotRequestContext), auth handling (BotAuthenticationHandler), API client scoping, and schema helpers (ChannelAccount.GetAgentUser,AgentUser.FromAccount). - Update Agent 365 lifecycle handler APIs and value DTOs to
AgentUser*naming while keeping legacyvalueType/eventTypestring constants. - Refresh tests, docs, and samples to match the new naming model (including observability/baggage helpers).
Show a summary per file
| File | Description |
|---|---|
| core/test/Microsoft.Teams.Core.UnitTests/UserTokenClientTests.cs | Update request context stamping assertions to AgentUser. |
| core/test/Microsoft.Teams.Core.UnitTests/Schema/CoreActivityTests.cs | Update activity parsing tests to use GetAgentUser() + new property names. |
| core/test/Microsoft.Teams.Core.UnitTests/Http/BotRequestContextTests.cs | Rename context factory/merge/to-options tests to AgentUser. |
| core/test/Microsoft.Teams.Core.UnitTests/ConversationClientTests.cs | Update conversation client tests to derive AgentUser from From. |
| core/test/Microsoft.Teams.Apps.UnitTests/MessageActivityInputBuilderTests.cs | Update TeamsChannelAccount mapping tests for renamed agent fields. |
| core/test/Microsoft.Teams.Apps.UnitTests/Diagnostics/BaggageBuilderTests.cs | Update baggage tests for AgentUser* setters/keys. |
| core/test/Microsoft.Teams.Apps.UnitTests/AgentLifecycleHandlerTests.cs | Update lifecycle handler tests to OnAgentUser* and renamed value types. |
| core/test/Microsoft.Teams.Apps.BotBuilder.UnitTests/TeamsApiClientTests.cs | Update compat client tests to pass AgentUser via inbound request context. |
| core/test/IntegrationTests/README.md | Rename integration-test terminology to “Agent user” + new runsettings names. |
| core/test/IntegrationTests/IntegrationTestFixture.cs | Update fixture to build/use AgentUser and scope ApiClient accordingly. |
| core/test/IntegrationTests/CreateConversationTests.cs | Update create-conversation tests to pass FromAgentUser(...). |
| core/test/IntegrationTests/CreateConversationDiagnosticTests.cs | Update diagnostics to stamp AgentUser into request options. |
| core/test/IntegrationTests/ConversationClientTests.cs | Update conversation operations to pass AgentUser request context and updated skip messages. |
| core/test/IntegrationTests/CompatTeamsInfoTests.cs | Update compat TeamsInfo integration tests to use AgentUser context + properties. |
| core/test/IntegrationTests/ApiClientTests.cs | Update integration tests for scoped ApiClient via ForAgentUser(...). |
| core/src/Microsoft.Teams.Core/Schema/CoreActivity.cs | Copy agent-related typed fields using new property names. |
| core/src/Microsoft.Teams.Core/Schema/ChannelAccount.cs | Rename typed agent fields + provide GetAgentUser() helper while keeping legacy JSON names. |
| core/src/Microsoft.Teams.Core/Schema/AgentUser.cs | Add new AgentUser DTO + FromAccount(ChannelAccount?) factory. |
| core/src/Microsoft.Teams.Core/Schema/AgenticIdentity.cs | Remove old AgenticIdentity DTO. |
| core/src/Microsoft.Teams.Core/README.md | Update public-surface docs to AgentUser. |
| core/src/Microsoft.Teams.Core/Http/BotRequestOptions.cs | Update comments to refer to agent user request context. |
| core/src/Microsoft.Teams.Core/Http/BotRequestContext.cs | Rename keys/properties/factories to AgentUser. |
| core/src/Microsoft.Teams.Core/Http/BotHttpClient.cs | Update comments for request option stamping. |
| core/src/Microsoft.Teams.Core/Hosting/BotAuthenticationHandler.cs | Read AgentUser from request options and acquire agent-user token when present. |
| core/src/Microsoft.Teams.Core/BotApplication.cs | Rename public send overload parameter to AgentUser. |
| core/src/Microsoft.Teams.Apps/TeamsBotApplication.cs | Rename SendAsync/ReplyAsync parameters and docs to AgentUser. |
| core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs | Map ChannelAccount agent fields to TeamsChannelAccount renamed fields. |
| core/src/Microsoft.Teams.Apps/Handlers/AgentLifecycleHandler.Values.cs | Rename lifecycle value DTOs/properties to AgentUser* naming (wire names preserved). |
| core/src/Microsoft.Teams.Apps/Handlers/AgentLifecycleHandler.cs | Rename lifecycle handler delegates + registration extensions to OnAgentUser*. |
| core/src/Microsoft.Teams.Apps/Handlers/AgentLifecycleHandler.Activity.cs | Rename lifecycle value/event constant identifiers while preserving legacy constant values. |
| core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs | Rename agent baggage setters + update extraction logic to new fields. |
| core/src/Microsoft.Teams.Apps/Diagnostics/AgentObservabilityKeys.cs | Rename internal constant identifiers for agent user baggage keys. |
| core/src/Microsoft.Teams.Apps/Context.cs | Update docs to reference agent user scoping from inbound recipient. |
| core/src/Microsoft.Teams.Apps/Api/Clients/TeamClient.cs | Plumb AgentUser into client-scoped request options. |
| core/src/Microsoft.Teams.Apps/Api/Clients/ReactionClient.cs | Plumb AgentUser into reaction operations request context. |
| core/src/Microsoft.Teams.Apps/Api/Clients/MemberClient.cs | Plumb AgentUser into member operations request context. |
| core/src/Microsoft.Teams.Apps/Api/Clients/MeetingClient.cs | Plumb AgentUser into meeting operations request options. |
| core/src/Microsoft.Teams.Apps/Api/Clients/ConversationApiClient.cs | Plumb AgentUser into conversation/activity/member/reaction operations. |
| core/src/Microsoft.Teams.Apps/Api/Clients/ApiClient.cs | Rename identity scoping to ForAgentUser and bind from inbound activity recipient. |
| core/src/Microsoft.Teams.Apps/Api/Clients/ActivityClient.cs | Plumb AgentUser into activity operations. |
| core/src/Microsoft.Teams.Apps.BotBuilder/CompatUserTokenClient.cs | Update compat docs/comments to “agent user”. |
| core/src/Microsoft.Teams.Apps.BotBuilder/CompatConversations.cs | Update compat docs/comments to “agent user”. |
| core/samples/PABot/RoutedTokenAcquisitionService.cs | Rename sample token routing API to AcquireTokenForAgentUserAsync. |
| core/samples/PABot/PACustomAuthHandler.cs | Update sample custom auth handler to read AgentUser from request options. |
| core/samples/PABot/InitCompatAdapter.cs | Update sample auth validation comments to “agent app instance”. |
| core/samples/ObservabilityBot/ObservabilityBotApp.cs | Update sample to read agent details from AgentAppInstanceId/AgentUserId. |
| core/samples/CompatBot/EchoBot.cs | Update sample to pass AgentUser request context. |
| core/samples/Agent365/README.md | Update sample docs to OnAgentUser* handler naming. |
| core/samples/Agent365/Program.cs | Update sample lifecycle handlers/value DTO types to AgentUser*. |
| core/README.md | Update top-level README auth wording to “agent user”. |
| core/docs/Observability-Design.md | Update observability design doc to new baggage builder setter names and field mapping. |
| core/docs/CompatTeamsInfo-API-Mapping.md | Update mapping doc to AgentUser terminology. |
| core/docs/Architecture.md | Update architecture doc diagrams/tables to AgentUser. |
| core/docs/ApiClient-Design.md | Update API client design doc to refer to agent user scoping. |
| core/docs/Activity-Design.md | Update activity design doc to AgentUser terminology and flow. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (2)
core/docs/Activity-Design.md:26
AgentUser.FromAccount(...)is documented as takingConversationAccount?, but the actual API isAgentUser.FromAccount(ChannelAccount?). The parameter type in the diagram should match the public surface to avoid confusion.
AgentUser (Core)
├── AgentAppInstanceId, AgentUserId, AgentIdentityBlueprintId
└── FromAccount(ConversationAccount?) — factory from typed fields
core/docs/Activity-Design.md:89
- The "CoreActivity declares typed properties" table lists
From/RecipientasConversationAccount?, but CoreActivity usesChannelAccount?in this repo. Aligning the type name here will prevent readers from searching for a non-existentConversationAccounttype.
| `Conversation` | `Conversation` (non-nullable) | URL construction, always initialized |
| `From` | `ConversationAccount?` | AgentUser extraction |
| `Recipient` | `ConversationAccount?` | IsTargeted flag for targeted messaging |
- Files reviewed: 55/55 changed files
- Comments generated: 3
- Review effort level: Low
| @@ -20,8 +20,8 @@ ConversationAccount (Core) | |||
| │ agenticAppId, agenticUserId, agenticAppBlueprintId | |||
| └── [JsonExtensionData] Properties bag for channel-specific fields | |||
There was a problem hiding this comment.
Review details
Comments suppressed due to low confidence (3)
core/docs/Activity-Design.md:25
- Activity-Design.md lists AgenticUser.FromAccount as taking ConversationAccount?, but CoreActivity.From/Recipient use Microsoft.Teams.Core.Schema.ChannelAccount and AgenticUser.FromAccount is defined against ChannelAccount. Update the signature in the diagram to avoid pointing readers to a non-existent type.
└── FromAccount(ConversationAccount?) — factory from typed fields
core/docs/Activity-Design.md:308
- The Agent User Flow example assigns activity.From = ConversationAccount, but CoreActivity.From is a ChannelAccount. This example should use ChannelAccount to match the actual schema types.
→ activity.From = ConversationAccount { Id="bot1", AgenticAppInstanceId="app-123", AgenticUserId="user-456" }
core/test/IntegrationTests/CreateConversationDiagnosticTests.cs:63
- CreateConversationDiagnosticTests sets the agentic user request option key via the literal string "AgenticUser". Using BotRequestContext.AgenticUserKey avoids key drift if the well-known option key ever changes.
- Files reviewed: 53/53 changed files
- Comments generated: 3
- Review effort level: Low
| ## Authentication | ||
|
|
||
| All methods use `AgenticIdentity` extracted from the turn context activity properties for authentication with the Teams services. The identity is obtained by converting the Bot Framework `Activity` to a `CoreActivity` and extracting agentic properties from `From.Properties`. | ||
| All methods use `AgenticUser` extracted from the turn context activity properties for authentication with the Teams services. The identity is obtained by converting the Bot Framework `Activity` to a `CoreActivity` and extracting agentic user properties from `From.Properties`. |
| <TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||
| <WarningsNotAsErrors>$(WarningsNotAsErrors);NU1903</WarningsNotAsErrors> | ||
| <GenerateDocumentationFile>true</GenerateDocumentationFile> |
| <TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||
| <WarningsNotAsErrors>$(WarningsNotAsErrors);NU1903</WarningsNotAsErrors> |
5dc0e19 to
8d63fc3
Compare
| <PropertyGroup> | ||
| <AnalysisLevel>latest-all</AnalysisLevel> | ||
| <TreatWarningsAsErrors>true</TreatWarningsAsErrors> | ||
| <WarningsNotAsErrors>$(WarningsNotAsErrors);NU1903</WarningsNotAsErrors> |
| { | ||
| _serviceUrl = serviceUrl; | ||
| _client = client; | ||
| _agenticIdentity = agenticIdentity; |
There was a problem hiding this comment.
Agentic id contains app id and user id right ? (and agentic id feels analogous to bot id) , I'm not sure if we should change this
There was a problem hiding this comment.
So according Anand,
Agentic Identity is a confusing term, and we should not use it.
AgenticUser means it has an app instance id (aka app id) AND a user id.
Does that make sense? Let me know if you want to chat about this.
8d63fc3 to
373fffd
Compare
Rename the Agent 365 SDK-facing identity model from AgenticIdentity to AgenticUser and align app instance/blueprint terminology with AgenticAppInstance and AgenticBlueprint. Preserve service-owned Activity wire values such as agenticUserId, agenticAppId, agenticAppBlueprintId, agenticAppInstanceId, and agentIdentityBlueprintId. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1f597d5b-5e98-4c0d-80d3-ef0962deda74
373fffd to
caf81cd
Compare
c45a871 to
1d69eef
Compare
| /// </summary> | ||
| /// <param name="agenticUser">The agentic user.</param> | ||
| /// <returns>The context carrying an <see cref="AgenticIdentity"/> created from <paramref name="agenticUser"/>.</returns> | ||
| public static BotRequestContext FromAgenticUser(AgenticUser agenticUser) |
There was a problem hiding this comment.
Let's not have so many methods, I think we should create agentic user or agentic app instance from channel account and agentic id from those. So many convenience wrappers also become confusing, wdyt ?
| /// Tenant ID associated with the agentic identity. | ||
| /// Gets the agentic app instance ID. | ||
| /// </summary> | ||
| public string? TenantId { get; set; } |
There was a problem hiding this comment.
this needs to come back
Reintroduce AgenticIdentity as the canonical request/proactive/API scoping carrier while keeping AgenticUser as the Teams/activity-facing model. API clients and request contexts now scope through AgenticIdentity, with AgenticUser convenience conversion preserved where appropriate. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1f597d5b-5e98-4c0d-80d3-ef0962deda74
1d69eef to
028bb77
Compare
| /// <summary> | ||
| /// Represents an agentic user for user-delegated token acquisition. | ||
| /// </summary> | ||
| public sealed class AgenticUser |
There was a problem hiding this comment.
Aamir do we need this class ? Isn't AgenticIdentity with "Kind" enough ?
|
Closing per the updated Agent 365 identity direction: C# stays as-is, and the AgenticIdentity-only follow-up work is continuing in Python/TypeScript. |
Summary
This keeps
AgenticUseras the concrete Teams/activity-facing identity model while making CoreAgenticIdentitythe SDK operation scope for request, proactive send, API-client, and auth plumbing. The carrier is created fromAgenticUsertoday and gives the SDK one canonical seam for future Agent 365 scopes without spreading new overloads through every helper.Decisions
AgenticUserremains the activity domain object because Teams payloads still describe an agentic user.AgenticIdentityis a disciplined discriminated carrier for SDK operations, so low-level plumbing depends on the scope abstraction rather than one concrete subject type.agenticUserId,agenticAppId,agenticAppBlueprintId,agenticAppInstanceId, lifecycleAgenticUser.../agenticUser..., roleagenticUser, auth flow tagagentic, service-ownedagentIdentityBlueprintId, and upstreamWithAgentUserIdentity(...).AgenticIdentityKind.AgenticAppInstanceis present only as the future carrier shape. Adding real app-instance behavior should be one factory/wrapper at the canonical seam, not a broad overload set across sends and clients.Deferred
Actual
AgenticAppInstancebehavior/model support is future work; this PR only preserves the operation-scope shape needed to add it cleanly later.Reviewer tips
Start at Core schema and request plumbing (
ChannelAccount,AgenticUser,AgenticIdentity,BotRequestContext,BotAuthenticationHandler), then Apps API-client scoping/proactive send helpers, lifecycle handlers, and the Agent365/ObservabilityBot/PABot samples and focused tests.Testing
Focused Core activity/request tests passed, including
AgenticIdentityTests,BotRequestContextTests,UserTokenClientTests,CoreActivityTests, andConversationClientTestson net8.0/net10.0. Focused Apps lifecycle/activity/diagnostics tests and BotBuilderTeamsApiClientTestspassed; changed Agent365, ObservabilityBot, PABot, and CompatBot samples built successfully;IntegrationTestsbuilt successfully;git diff --checkpassed. Earlier live Teams smoke test passed withcore/samples/Agent365/Agent365.csprojand Teams agentic userDemo Test 2, confirming inbound parsing and outbound echo behavior without exposing secrets.