Skip to content

Add Api Clients with Reactions and Targeted Message support#334

Open
rido-min wants to merge 20 commits intonext/corefrom
next/core-api-clients
Open

Add Api Clients with Reactions and Targeted Message support#334
rido-min wants to merge 20 commits intonext/corefrom
next/core-api-clients

Conversation

@rido-min
Copy link
Member

Introduced a structured API facade (TeamsBotApplication.Api) for Teams operations, grouping functionality into Conversations, Users, Teams, Meetings, and Batch sub-APIs. Added new classes for each sub-API, with extensive XML documentation. Updated TeamsBotApplication to expose the new facade. Added integration tests for the API hierarchy and error handling. Cleaned up .csproj by removing unused RunSettings property. This refactor improves discoverability, organization, and developer experience for Teams API usage.

This pull request introduces a new ActivitiesApi class to the codebase, which provides a unified interface for performing activity-related operations in conversations, such as sending, updating, deleting activities, handling conversation history, and retrieving activity members. The class wraps existing functionality from the ConversationClient, making these operations easier to use and more consistent throughout the application.

New API for activity operations:

  • Added the ActivitiesApi class in core/src/Microsoft.Teams.Bot.Apps/Api/ActivitiesApi.cs, providing methods for sending, updating, and deleting activities, uploading conversation history, and retrieving activity members.
  • Introduced overloads for delete and send history methods, allowing operations to be performed either by explicit IDs and URLs or by passing activity objects, improving flexibility and usability.

Integration and usability improvements:

  • All methods delegate to the underlying ConversationClient, ensuring consistency and reusability of existing logic.
  • Added support for optional custom headers and agentic identity parameters to enhance authentication and request customization.
  • Comprehensive XML documentation added to all methods, improving code clarity and maintainability.

Introduced a structured API facade (`TeamsBotApplication.Api`) for Teams operations, grouping functionality into Conversations, Users, Teams, Meetings, and Batch sub-APIs. Added new classes for each sub-API, with extensive XML documentation. Updated `TeamsBotApplication` to expose the new facade. Added integration tests for the API hierarchy and error handling. Cleaned up `.csproj` by removing unused RunSettings property. This refactor improves discoverability, organization, and developer experience for Teams API usage.
@rido-min rido-min marked this pull request as ready for review February 17, 2026 18:55
Added detailed tables to README.md mapping TeamsApi facade methods to their underlying REST endpoints. Documentation covers Conversations, Users (Token), Teams, Meetings, and Batch operations, including HTTP methods, endpoint paths, and relevant base URLs. Added notes on service URL usage and path parameter encoding.
Copy link
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

This PR introduces a hierarchical Teams API facade surfaced as TeamsBotApplication.Api, organizing Teams operations into sub-APIs (Conversations/Activities/Members, Users/Token, Teams, Meetings, Batch) and adding integration tests to validate the facade structure and delegation.

Changes:

  • Added TeamsApi facade with sub-API classes for common Teams operations (activities, members, users/tokens, teams, meetings, batch).
  • Updated TeamsBotApplication to expose the facade via a new Api property.
  • Added integration tests covering API hierarchy and some error-handling behavior; removed an unused RunSettingsFilePath property from the test project.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
core/test/Microsoft.Teams.Bot.Core.Tests/TeamsApiFacadeTests.cs Adds integration tests for the new TeamsBotApplication.Api hierarchy and delegations.
core/test/Microsoft.Teams.Bot.Core.Tests/Microsoft.Teams.Bot.Core.Tests.csproj Removes unused RunSettingsFilePath property group.
core/src/Microsoft.Teams.Bot.Apps/TeamsBotApplication.cs Exposes new Api facade via lazy-initialized property.
core/src/Microsoft.Teams.Bot.Apps/Api/TeamsApi.cs Defines top-level hierarchical facade and wires up sub-APIs.
core/src/Microsoft.Teams.Bot.Apps/Api/ConversationsApi.cs Adds container for conversation-scoped APIs (Activities/Members).
core/src/Microsoft.Teams.Bot.Apps/Api/ActivitiesApi.cs Adds activity operations wrapper around ConversationClient.
core/src/Microsoft.Teams.Bot.Apps/Api/MembersApi.cs Adds conversation member operations wrapper around ConversationClient.
core/src/Microsoft.Teams.Bot.Apps/Api/UsersApi.cs Adds container for user-scoped APIs (Token).
core/src/Microsoft.Teams.Bot.Apps/Api/UserTokenApi.cs Adds user token operations wrapper around UserTokenClient.
core/src/Microsoft.Teams.Bot.Apps/Api/TeamsOperationsApi.cs Adds team/channel operations wrapper around TeamsApiClient.
core/src/Microsoft.Teams.Bot.Apps/Api/MeetingsApi.cs Adds meeting operations wrapper around TeamsApiClient.
core/src/Microsoft.Teams.Bot.Apps/Api/BatchApi.cs Adds batch messaging and batch-operation management wrapper around TeamsApiClient.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +56 to +62
ArgumentNullException.ThrowIfNull(activity);
return _client.GetTokenAsync(
activity.From.Id!,
connectionName,
activity.ChannelId!,
code,
cancellationToken);
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The activity-context overload uses null-forgiving operators for required fields (e.g., activity.From.Id and activity.ChannelId) but doesn’t validate them. If ChannelId/From.Id are missing, null can flow into UserTokenClient and result in confusing downstream failures or invalid requests. Add explicit validation (e.g., ThrowIfNullOrWhiteSpace on From.Id and ChannelId) for all activity-context methods in this API to fail fast with clear exceptions.

Copilot uses AI. Check for mistakes.
Comment on lines +104 to +112
ArgumentNullException.ThrowIfNull(activity);
return _client.FetchParticipantAsync(
meetingId,
participantId,
activity.ChannelData?.Tenant?.Id ?? throw new InvalidOperationException("Tenant ID not available in activity"),
activity.ServiceUrl!,
activity.From.GetAgenticIdentity(),
customHeaders,
cancellationToken);
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

This throws InvalidOperationException when tenant ID is missing from the provided activity. Since this is invalid caller input (the argument doesn’t contain required data), prefer ArgumentException/ArgumentNullException (or ThrowIfNull/ThrowIfNullOrWhiteSpace) to keep exception semantics consistent with other argument validation across the clients.

Copilot uses AI. Check for mistakes.
Comment on lines +64 to +72
ArgumentNullException.ThrowIfNull(contextActivity);
return _client.SendMessageToListOfUsersAsync(
activity,
teamsMembers,
contextActivity.ChannelData?.Tenant?.Id ?? throw new InvalidOperationException("Tenant ID not available in activity"),
contextActivity.ServiceUrl!,
contextActivity.From.GetAgenticIdentity(),
customHeaders,
cancellationToken);
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

This throws InvalidOperationException when tenant ID is missing from the provided activity. Because the tenant ID is required input derived from the argument, use an argument validation exception (ArgumentException/ArgumentNullException) for consistency and clearer caller feedback.

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +51
public TeamsApi Api => _api ??= new TeamsApi(
ConversationClient,
UserTokenClient,
_teamsApiClient);
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

Api is lazily initialized on a singleton TeamsBotApplication without synchronization. Concurrent calls can create multiple TeamsApi instances and fail the “same instance” guarantee under load. Consider initializing in the constructor, using Lazy, or protecting the initialization with a lock/Interlocked to make it thread-safe.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

Choose a reason for hiding this comment

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

@rido-min copilot has a good point here, let's initialize this in the constructor?

@rido-min rido-min added the CORE label Feb 17, 2026
Introduces ReactionsApi for programmatic message reactions in Teams bots, with AddAsync and DeleteAsync methods. ConversationClient now supports AddReactionAsync and DeleteReactionAsync. Expanded ReactionTypes with more documented types. Demonstrated usage in Program.cs by adding a "cake" reaction to "hello" messages.
/// <param name="customHeaders">Optional custom headers to include in the request.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the response with the ID of the updated activity.</returns>
public Task<UpdateActivityResponse> UpdateAsync(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Wondering why we have disparity between send and update in extracting conv id/ activity id from activity itself? maybe we should have an overload for it similar to all other apis?

/// <param name="customHeaders">Optional custom headers to include in the request.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public Task DeleteAsync(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need this overload for teamsactivity ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

good point, having the overload defeats the benefits of polymorphism

/// <item><see cref="Members"/> - Member operations (get, delete)</item>
/// </list>
/// </remarks>
public class ConversationsApi
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't there be a method here for create conversation? intentional omission?

/// <param name="customHeaders">Optional custom headers to include in the request.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the conversation member.</returns>
public Task<T> GetByIdAsync<T>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we combine GetByIdAsync<T and GetByIdAsync<ConversationAccount to GetByIdAsync <TeamsConversationAccount

/// <param name="customHeaders">Optional custom headers to include in the request.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the team details.</returns>
public Task<TeamDetails> GetByIdAsync(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should teamId also be extracted from activity here ? from activity.channelData.team.id

/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains the list of channels.</returns>
public Task<ChannelList> GetChannelsAsync(
string teamId,
Copy link
Collaborator

Choose a reason for hiding this comment

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

^ same
Should teamId also be extracted from activity here ? from activity.channelData.team.id

/// <param name="customHeaders">Optional custom headers to include in the request.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public Task DeleteAsync(
Copy link
Collaborator

Choose a reason for hiding this comment

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

good point, having the overload defeats the benefits of polymorphism

/// <param name="customHeaders">Optional custom headers to include in the request.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains a list of members for the activity.</returns>
public Task<IList<ConversationAccount>> GetMembersAsync(
Copy link
Collaborator

Choose a reason for hiding this comment

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

what does "members of a specific activity" even mean? is it members of the conversation in which this activity was posted?

Comment on lines +48 to +51
public TeamsApi Api => _api ??= new TeamsApi(
ConversationClient,
UserTokenClient,
_teamsApiClient);
Copy link
Collaborator

Choose a reason for hiding this comment

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

@rido-min copilot has a good point here, let's initialize this in the constructor?

rido-min and others added 3 commits March 3, 2026 20:04
Major update adding strong-typed handlers and payloads for all Teams invoke and event activity types (adaptive card actions, file consent, task modules, message extensions, meetings, etc.). Introduces new handler registration APIs, extensible InvokeResponse, and builder classes for adaptive card, task module, and message extension responses. Refactors schema for nullability and type-safety, unifies activity/entity types, and improves router logic. Adds new sample bots and documentation. Enhances logging, DI, and test coverage. Removes legacy code and improves maintainability throughout.
Added ArgumentNullException.ThrowIfNull for critical properties in API wrappers to ensure required parameters are not null. Refactored IConfiguration retrieval using pattern matching for clarity. Updated .slnx to exclude certain sample projects from default build. Modernized bearer token extraction and cleaned up unused usings. These changes improve code safety, error reporting, and maintainability.
@rido-min rido-min requested a review from Copilot March 4, 2026 04:21
Copy link
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 20 out of 20 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ArgumentException.ThrowIfNullOrWhiteSpace(reactionType);
ArgumentNullException.ThrowIfNull(serviceUrl);

string url = $"{serviceUrl.ToString().TrimEnd('/')}/v3/conversations/{conversationId}/activities/{activityId}/reactions/{reactionType}";
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

The reaction URL is constructed with unencoded path segments (conversationId, activityId, reactionType). This can break requests (or change meaning) when IDs contain characters that need escaping. Use Uri.EscapeDataString(...) (or an equivalent segment-encoding approach) for each path segment before interpolation.

Copilot uses AI. Check for mistakes.
activity.Id,
reactionType,
activity.ServiceUrl,
activity.Recipient?.GetAgenticIdentity(),
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

The activity-context overload uses activity.Recipient?.GetAgenticIdentity() as the agentic identity. Other API surfaces in this PR use activity.From?.GetAgenticIdentity() for caller identity; using Recipient (typically the bot) is inconsistent and likely incorrect for OBO/auth context. Consider switching to activity.From?.GetAgenticIdentity() (and make the same change in the Delete overload).

Suggested change
activity.Recipient?.GetAgenticIdentity(),
activity.From?.GetAgenticIdentity(),

Copilot uses AI. Check for mistakes.
Comment on lines +181 to +185
ArgumentNullException.ThrowIfNull(activity);
ArgumentNullException.ThrowIfNull(activity.Id);
ArgumentNullException.ThrowIfNull(activity.Conversation);
ArgumentNullException.ThrowIfNull(activity.Conversation.Id);
ArgumentNullException.ThrowIfNull(activity.ServiceUrl);
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

These guards allow empty/whitespace IDs (activity.Id, activity.Conversation.Id) because they only check for null. Since these values are used as URL path segments, empty/whitespace will produce invalid endpoints. Consider using ArgumentException.ThrowIfNullOrWhiteSpace(...) for string IDs (matching patterns used elsewhere in the PR, e.g., ReactionsApi).

Copilot uses AI. Check for mistakes.
ArgumentNullException.ThrowIfNull(activity);
ArgumentNullException.ThrowIfNull(activity.ServiceUrl);
ArgumentNullException.ThrowIfNull(activity.Conversation);
ArgumentNullException.ThrowIfNull(activity.Conversation.Id);
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

Similar to ActivitiesApi, this only checks activity.Conversation.Id for null (not whitespace). Since it is used in URL construction, consider switching to ArgumentException.ThrowIfNullOrWhiteSpace(activity.Conversation.Id) in these activity-context overloads for more robust validation.

Suggested change
ArgumentNullException.ThrowIfNull(activity.Conversation.Id);
ArgumentException.ThrowIfNullOrWhiteSpace(activity.Conversation.Id);

Copilot uses AI. Check for mistakes.
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(activity);
ArgumentNullException.ThrowIfNull(activity);
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

Duplicate ArgumentNullException.ThrowIfNull(activity); call. Remove one to reduce noise and keep guard clauses consistent.

Suggested change
ArgumentNullException.ThrowIfNull(activity);

Copilot uses AI. Check for mistakes.
[Fact]
public async Task Api_Teams_GetByIdAsync()
{
string teamId = Environment.GetEnvironmentVariable("TEST_TEAMID") ?? throw new InvalidOperationException("TEST_TEAMID environment variable not set");
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

These tests hard-fail when required env vars are missing, which makes them brittle in typical CI/dev runs. Consider skipping tests when env vars aren’t set (e.g., using a skip mechanism or throwing Xunit.SkipException) so the suite can run without requiring external configuration.

Suggested change
string teamId = Environment.GetEnvironmentVariable("TEST_TEAMID") ?? throw new InvalidOperationException("TEST_TEAMID environment variable not set");
string? teamId = Environment.GetEnvironmentVariable("TEST_TEAMID");
if (string.IsNullOrEmpty(teamId))
{
throw new Xunit.SkipException("Skipping Api_Teams_GetByIdAsync because TEST_TEAMID environment variable is not set.");
}

Copilot uses AI. Check for mistakes.
{
await context.SendActivityAsync("Hi there! 👋 You said hello!", cancellationToken);

await teamsApp.Api.Conversations.Reactions.AddAsync(context.Activity, "cake", cancellationToken: cancellationToken);
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

The sample uses reaction type \"cake\", but the ReactionTypes constants in this repo don’t include it and the service may reject unknown reaction types. Use a known supported value (e.g., one of ReactionTypes.Like/Heart/Laugh/...) or explain in the sample why this custom value is valid.

Suggested change
await teamsApp.Api.Conversations.Reactions.AddAsync(context.Activity, "cake", cancellationToken: cancellationToken);
await teamsApp.Api.Conversations.Reactions.AddAsync(context.Activity, ReactionTypes.Like, cancellationToken: cancellationToken);

Copilot uses AI. Check for mistakes.
rido-min and others added 3 commits March 4, 2026 04:56
This pull request introduces support for message reactions in the Teams
bot SDK, along with improvements for targeted messaging. The changes add
a new `ReactionsApi` for handling reactions, expand the list of
supported reaction types, and enhance message delivery to allow
targeting specific recipients. The most important updates are grouped
below:

**Message Reaction Support**

* Added a new `ReactionsApi` class, enabling bots to add and remove
reactions (like, heart, laugh, etc.) on conversation activities. This
includes both direct and context-based methods for reaction management.
(`core/src/Microsoft.Teams.Bot.Apps/Api/ReactionsApi.cs`)
* Integrated `ReactionsApi` into `ConversationsApi`, exposing it via the
`Reactions` property and updating documentation to reflect its
availability.
(`core/src/Microsoft.Teams.Bot.Apps/Api/ConversationsApi.cs`)
[[1]](diffhunk://#diff-51d32bbdd7ca8e036814a550fdcc74432bd293f447a5b105cde5714f6feddde4R16)
[[2]](diffhunk://#diff-51d32bbdd7ca8e036814a550fdcc74432bd293f447a5b105cde5714f6feddde4R29)
[[3]](diffhunk://#diff-51d32bbdd7ca8e036814a550fdcc74432bd293f447a5b105cde5714f6feddde4R41-R45)
* Implemented `AddReactionAsync` and `DeleteReactionAsync` methods in
`ConversationClient` to support adding/removing reactions through HTTP
calls. (`core/src/Microsoft.Teams.Bot.Core/ConversationClient.cs`)

**Expanded Reaction Types**

* Extended the `ReactionTypes` class to include new reactions
(checkmark, hourglass, pushpin, exclamation) and clarified existing
reactions with emoji descriptions. Removed the unused `plusOne`
reaction.
(`core/src/Microsoft.Teams.Bot.Apps/Schema/MessageActivities/MessageReactionActivity.cs`)

**Targeted Messaging Enhancements**

* Added an `IsTargeted` property to `CoreActivity` and updated activity
cloning to preserve this flag, enabling messages to be directed
privately to specific recipients.
(`core/src/Microsoft.Teams.Bot.Core/Schema/CoreActivity.cs`)
[[1]](diffhunk://#diff-aa65632fe28a87aec3d29025384c7f1e687d5839d848f1220e8ed59e76dcd35bR60-R65)
[[2]](diffhunk://#diff-aa65632fe28a87aec3d29025384c7f1e687d5839d848f1220e8ed59e76dcd35bR159)
* Modified `SendActivityAsync`, `UpdateActivityAsync`, and
`DeleteActivityAsync` methods in `ConversationClient` to handle targeted
activities by appending the `isTargetedActivity=true` query parameter
when appropriate.
(`core/src/Microsoft.Teams.Bot.Core/ConversationClient.cs`)
[[1]](diffhunk://#diff-d62a8ce4aac677906758eb430b84c9432f61ff95342701fdcae909310e2aed27R54-R58)
[[2]](diffhunk://#diff-d62a8ce4aac677906758eb430b84c9432f61ff95342701fdcae909310e2aed27R91-R96)
[[3]](diffhunk://#diff-d62a8ce4aac677906758eb430b84c9432f61ff95342701fdcae909310e2aed27L110-R150)
[[4]](diffhunk://#diff-d62a8ce4aac677906758eb430b84c9432f61ff95342701fdcae909310e2aed27R181)
* Updated `CoreActivityBuilder` to allow specifying targeted recipients
via the `WithRecipient(recipient, isTargeted)` method.
(`core/src/Microsoft.Teams.Bot.Core/Schema/CoreActivityBuilder.cs`)

**Sample Usage**

* Enhanced the Teams bot sample (`core/samples/TeamsBot/Program.cs`) to
demonstrate reaction usage (adding a "cake" reaction when "hello" is
received) and sending targeted messages to conversation members.

These changes collectively make it easier for bot developers to manage
reactions and deliver targeted messages within Teams conversations.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Comment out or adjust assertions on Recipient in activity builder tests to reflect updated handling or population of the Recipient property. Update TeamsActivityBuilderTests to check From instead of Recipient where appropriate.
@rido-min rido-min changed the title Add hierarchical Teams API facade to TeamsBotApplication Add Api Clients with Reactions and Targeted Message support Mar 4, 2026
rido-min added 7 commits March 3, 2026 22:51
Refactored Conversation to use a primary constructor for id initialization. Updated ConversationClientTest to cache conversation ID, recipient, and agentic identity, and to consistently set the From property. Simplified test code by using the new Conversation(string id) constructor throughout. Added agentic identity support to relevant test calls. Introduced a new test for adding/removing message reactions. Improved error handling and parameter passing for paged member tests. These changes enhance test reliability, reduce duplication, and expand coverage for reaction APIs.
Add MartinCostello.Logging.XUnit to enable structured logging output in test runs. Update ConversationClientTest to accept ITestOutputHelper and configure logging to use xUnit output, with filters to reduce log noise. Pass _agenticIdentity to CreateConversationAsync. Reformat csproj for consistency.
Introduced logic in EchoBot to send a message and programmatically add/remove reactions ("laugh" and "sad") to it in Teams. Switched TeamsActivity to use a hardcoded service URL. Added WithServiceUrl(string) overload to CoreActivityBuilder for convenience. Updated tests to use new Conversation constructor and explicitly set Bot properties for improved clarity. Commented out SendUpdateDeleteActivityAsync in favor of new reaction logic.
Refactored integration test classes to use xUnit output logging via ITestOutputHelper, centralized environment variable handling in constructors, and removed redundant code. Updated all tests to use private fields for IDs and configuration, improved logging filters, and modernized test code for clarity and maintainability. No changes to test logic or assertions.
Introduce _agenticAppBlueprintId, _agenticAppId, and _agenticUserId fields to CompatTeamsInfoTests, initialized from environment variables. Use AzureAd__ClientId for botAppId and populate ChannelAccount properties with agentic identifiers to support new authentication and identity testing scenarios.
Major overhaul of TeamsBotApplication hosting model:
- Remove TeamsBotApplicationBuilder; use WebApplicationBuilder/WebApplication directly.
- Add AddTeamsBotApplication/UseBotApplication extension methods for registration and endpoint mapping.
- Support custom bot app classes and add CustomHosting sample.

Middleware pipeline improvements:
- Rename ITurnMiddleWare to ITurnMiddleware; change Use() to UseMiddleware().
- Update all usages, tests, and docs for new middleware API.

Service registration and API modernization:
- Rename AddAuthorization to AddBotAuthorization.
- Ensure AddHttpContextAccessor is always registered.
- Use explicit types, collection initializers, and modern C# features.
- Make ConversationClient/UserTokenClient methods virtual for testability.

Update all samples and tests to new hosting and middleware model.
Improve code clarity, nullability, and documentation throughout.
Add copyright headers and appsettings.json for new sample.
Introduce consistent JsonSerializerOptions for ConversationClient, applying them to all serialization for requests and logs. Improve log detail and consistency. Fix DeleteActivityAsync to properly await internal call. Increase Teams logging to Trace in tests. Add nullable TeamsApi field to TeamsBotApplication.
rido-min added 4 commits March 4, 2026 18:02
Introduce agentic identity to Teams API and conversation client tests by reading new environment variables and constructing AgenticIdentity objects. Pass agentic identity to relevant Teams API client and facade methods. Update exception and assertion tests accordingly. Mark or skip tests that are not compatible with agentic identity, and adjust test data where needed. These changes enable testing of agentic identity scenarios in Teams bot integration tests.
Updated message handling to explicitly mark targeted messages by setting the isTargeted property in outgoing activities. The IsTargeted property is now serialized in CoreActivity, ensuring this flag is included in activity JSON payloads for downstream processing. Enhanced reply logic to use TeamsActivity with targeted recipient and mention.
isTargeted is now serialized and deserialized in activity JSON.
Updated AdaptiveCardActivity.json and SuggestedActionsActivity.json
to include isTargeted. Adjusted related tests to expect and verify
the presence of isTargeted in JSON.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants