From 1b335326e9e1584ea32dfe090665dc262b9956ef Mon Sep 17 00:00:00 2001 From: heyitsaamir Date: Fri, 26 Jun 2026 15:12:29 -0700 Subject: [PATCH 1/5] Add optional TenantId to AgenticIdentity Expose the agentic tenant id end-to-end: add a typed tenantId to the base ChannelAccount (the wire source), surface it through GetAgenticIdentity and AgenticIdentity.FromAccount, and add AgenticIdentity.TenantId. The duplicate tenantId on TeamsChannelAccount is removed in favor of the inherited base property (same JSON name, no behavior change). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Diagnostics/TeamsBaggageBuilder.cs | 2 +- .../Schema/TeamsChannelAccount.cs | 6 --- .../Schema/AgenticIdentity.cs | 8 +++- .../Schema/ChannelAccount.cs | 9 +++- .../Schema/CoreActivityTests.cs | 45 +++++++++++++++++++ 5 files changed, 61 insertions(+), 9 deletions(-) diff --git a/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs b/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs index 49aff4f8..8789cbdd 100644 --- a/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs +++ b/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs @@ -96,7 +96,7 @@ public TeamsBaggageBuilder Set(string key, string? value) /// /// Populates every baggage key reachable from ctx.Activity — including the Apps-only keys /// backed by . Tenant fallback uses the typed - /// when is null. + /// when is null. /// public TeamsBaggageBuilder FromTeamsContext(Context ctx) where TActivity : TeamsActivity { diff --git a/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs b/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs index df0544bf..2d0033d2 100644 --- a/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs +++ b/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs @@ -103,10 +103,4 @@ public TeamsChannelAccount() /// [JsonPropertyName("userRole")] public string? UserRole { get; set; } - - /// - /// Gets or sets the Microsoft Entra tenant ID associated with this account. - /// - [JsonPropertyName("tenantId")] - public string? TenantId { get; set; } } diff --git a/core/src/Microsoft.Teams.Core/Schema/AgenticIdentity.cs b/core/src/Microsoft.Teams.Core/Schema/AgenticIdentity.cs index 2f43804f..faf676ce 100644 --- a/core/src/Microsoft.Teams.Core/Schema/AgenticIdentity.cs +++ b/core/src/Microsoft.Teams.Core/Schema/AgenticIdentity.cs @@ -17,6 +17,11 @@ public sealed class AgenticIdentity /// public string? AgenticUserId { get; set; } + /// + /// Tenant ID associated with the agentic identity. + /// + public string? TenantId { get; set; } + /// /// Agentic application blueprint ID. /// @@ -37,7 +42,8 @@ public sealed class AgenticIdentity { AgenticAppId = account.AgenticAppId, AgenticUserId = account.AgenticUserId, - AgenticAppBlueprintId = account.AgenticAppBlueprintId + AgenticAppBlueprintId = account.AgenticAppBlueprintId, + TenantId = account.TenantId }; } } diff --git a/core/src/Microsoft.Teams.Core/Schema/ChannelAccount.cs b/core/src/Microsoft.Teams.Core/Schema/ChannelAccount.cs index d2e3849e..7e466b46 100644 --- a/core/src/Microsoft.Teams.Core/Schema/ChannelAccount.cs +++ b/core/src/Microsoft.Teams.Core/Schema/ChannelAccount.cs @@ -49,6 +49,12 @@ public class ChannelAccount() [JsonPropertyName("agenticAppBlueprintId")] public string? AgenticAppBlueprintId { get; set; } + /// + /// Gets or sets the tenant ID associated with the account. + /// + [JsonPropertyName("tenantId")] + public string? TenantId { get; set; } + /// /// Gets the extension data dictionary for storing additional properties not defined in the schema. /// @@ -71,7 +77,8 @@ public class ChannelAccount() { AgenticAppId = AgenticAppId, AgenticUserId = AgenticUserId, - AgenticAppBlueprintId = AgenticAppBlueprintId + AgenticAppBlueprintId = AgenticAppBlueprintId, + TenantId = TenantId }; } } diff --git a/core/test/Microsoft.Teams.Core.UnitTests/Schema/CoreActivityTests.cs b/core/test/Microsoft.Teams.Core.UnitTests/Schema/CoreActivityTests.cs index e56f475a..fc6d0fb8 100644 --- a/core/test/Microsoft.Teams.Core.UnitTests/Schema/CoreActivityTests.cs +++ b/core/test/Microsoft.Teams.Core.UnitTests/Schema/CoreActivityTests.cs @@ -330,4 +330,49 @@ public void IsTargeted_DeserializedFromJson() Assert.Equal("user-123", activity.Recipient.Id); Assert.True(activity.Recipient.IsTargeted); } + + [Fact] + public void AgenticIdentity_IncludesTenantId_FromRecipient() + { + string json = """ + { + "type": "message", + "recipient": { + "id": "28:bot-id", + "agenticAppId": "agentic-app", + "agenticUserId": "agentic-user", + "agenticAppBlueprintId": "blueprint", + "tenantId": "tenant-abc" + } + } + """; + + CoreActivity activity = CoreActivity.FromJsonString(json); + + AgenticIdentity? identity = activity.Recipient?.GetAgenticIdentity(); + Assert.NotNull(identity); + Assert.Equal("agentic-app", identity!.AgenticAppId); + Assert.Equal("agentic-user", identity.AgenticUserId); + Assert.Equal("blueprint", identity.AgenticAppBlueprintId); + Assert.Equal("tenant-abc", identity.TenantId); + } + + [Fact] + public void AgenticIdentity_TenantIdAlone_DoesNotCreateIdentity() + { + string json = """ + { + "type": "message", + "recipient": { + "id": "user-123", + "tenantId": "tenant-abc" + } + } + """; + + CoreActivity activity = CoreActivity.FromJsonString(json); + + Assert.Equal("tenant-abc", activity.Recipient?.TenantId); + Assert.Null(activity.Recipient?.GetAgenticIdentity()); + } } From 5b6efa0d0eafd4957dd6d94060ec04a42a463503 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Jun 2026 22:34:17 +0000 Subject: [PATCH 2/5] Fix TeamsChannelAccount.FromChannelAccount to copy TenantId from typed property --- core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs b/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs index 2d0033d2..09e366e7 100644 --- a/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs +++ b/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs @@ -54,7 +54,7 @@ public TeamsChannelAccount() result.Email = result.Properties.Extract("email"); result.UserPrincipalName = result.Properties.Extract("userPrincipalName"); result.UserRole = result.Properties.Extract("userRole"); - result.TenantId = result.Properties.Extract("tenantId"); + result.TenantId = channelAccount.TenantId; if (string.IsNullOrEmpty(result.AadObjectId)) { result.AadObjectId = result.ObjectId; From 50eb9adb4359bbbbae549dc027e9e355fdaac82f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Jun 2026 22:38:03 +0000 Subject: [PATCH 3/5] Restore explicit TenantId property to TeamsChannelAccount --- core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs b/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs index 09e366e7..2ec463e9 100644 --- a/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs +++ b/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs @@ -103,4 +103,10 @@ public TeamsChannelAccount() /// [JsonPropertyName("userRole")] public string? UserRole { get; set; } + + /// + /// Gets or sets the Microsoft Entra tenant ID associated with this account. + /// + [JsonPropertyName("tenantId")] + public new string? TenantId { get; set; } } From fcbd2439709778933f42c1f554946ae33584aa63 Mon Sep 17 00:00:00 2001 From: Mehak Bindra Date: Fri, 26 Jun 2026 15:40:21 -0700 Subject: [PATCH 4/5] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs b/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs index 8789cbdd..49aff4f8 100644 --- a/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs +++ b/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs @@ -96,7 +96,7 @@ public TeamsBaggageBuilder Set(string key, string? value) /// /// Populates every baggage key reachable from ctx.Activity — including the Apps-only keys /// backed by . Tenant fallback uses the typed - /// when is null. + /// when is null. /// public TeamsBaggageBuilder FromTeamsContext(Context ctx) where TActivity : TeamsActivity { From 0a08fed969a04ecc58c7ddcba328a0140e4c6053 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 26 Jun 2026 22:42:33 +0000 Subject: [PATCH 5/5] Remove explicit TenantId from TeamsChannelAccount; fix cref in TeamsBaggageBuilder --- .../Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs | 2 +- core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs b/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs index 49aff4f8..23d4190c 100644 --- a/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs +++ b/core/src/Microsoft.Teams.Apps/Diagnostics/TeamsBaggageBuilder.cs @@ -96,7 +96,7 @@ public TeamsBaggageBuilder Set(string key, string? value) /// /// Populates every baggage key reachable from ctx.Activity — including the Apps-only keys /// backed by . Tenant fallback uses the typed - /// when is null. + /// when is null. /// public TeamsBaggageBuilder FromTeamsContext(Context ctx) where TActivity : TeamsActivity { diff --git a/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs b/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs index 2ec463e9..09e366e7 100644 --- a/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs +++ b/core/src/Microsoft.Teams.Apps/Schema/TeamsChannelAccount.cs @@ -103,10 +103,4 @@ public TeamsChannelAccount() /// [JsonPropertyName("userRole")] public string? UserRole { get; set; } - - /// - /// Gets or sets the Microsoft Entra tenant ID associated with this account. - /// - [JsonPropertyName("tenantId")] - public new string? TenantId { get; set; } }