Skip to main content

Agents Can Now Send Reactions to Messages in Microsoft Teams

Public Preview | May 2026

Your Teams agents can now react to messages with emojis. You can acknowledge, confirm, celebrate, and listen without sending an extra message reply. Agent message reactions are available today in public preview across .NET, TypeScript, and Python.

Contoso agent identified as the sender of a reaction on a user message

The Problem: Messages Can Be Too Noisyโ€‹

Every interaction your agent has today requires a new message to be sent, yet another reply cluttering an already busy thread.

Meanwhile, humans communicate volumes with a single ๐Ÿ‘.

Agent reactions bridge that gap. Your agent can now participate in the lightweight, non-verbal layer of conversation that makes Teams collaboration feel natural.

What You Can Doโ€‹

CapabilityDescription
Add reactionsReact to any message your agent can see - 1:1, group chat, or channel
Remove reactionsProgrammatically remove reactions as context changes
Receive reaction eventsGet notified when users react to your agent's messages
Teams Reaction ReferenceDiscover all available emojis and their skin tone variants

Real-World Scenariosโ€‹

1. Instant Acknowledgmentโ€‹

Agents can react to a request with a simple ๐Ÿ‘ (like). No additionl messages, and users know their request has been heard

2. Progress Signalingโ€‹

Agents can react to acknowledge a request, then swap their reaction to a different one signaling their work has been completed. Agent tasks run in the background without additional thread noise.

Below is an example of an agent reacting to a message with โŒ› holdon, then swapping that for a โœ… 2705_whiteheavycheckmark when the task is complete.

Teams Reaction Reference

You can find the complete list of emojis for use on Teams and their associated EmojiID on the Teams Reactions Reference page

// Acknowledge user request and notify them work has commenced with an hourglass "holdon" emoji
// Add reaction to message
await context.Api.Conversations.Reactions.AddAsync(
context.Activity.Conversation.Id,
context.Activity.Id,
new ReactionType("holdon"),
cancellationToken
);

// ... task completes ...

// Swap to checkmark emoji to indicate task completion
// Remove previously added hourglass "holdon" emoji
await context.Api.Conversations.Reactions.DeleteAsync(
context.Activity.Conversation.Id,
context.Activity.Id,
new ReactionType("holdon"),
cancellationToken
);

// Add new checkmark '2705_whiteheavycheckmark" reaction to signal work is complete
await context.Api.Conversations.Reactions.AddAsync(
context.Activity.Conversation.Id,
context.Activity.Id,
new ReactionType("2705_whiteheavycheckmark"),
cancellationToken
);

3. Silent Celebrationsโ€‹

Agent monitors a channel for deployments, launches, or other celebratory events and joins in by reacting with ๐Ÿฅณ party.

Adding a Reactionโ€‹

You can utilize lightweight communication with reactions to acknowledge a message with a simple ๐Ÿ‘ like, below are examples of doing so in each language:

TypeScriptโ€‹

// Add a reaction
app.on('message', async ({ activity, api, send }) => {
await send("Hello! I'll react to your message.");

// Add a reaction to the incoming message
await api.reactions.add(activity.conversation.id, activity.id, 'like');
});

.NETโ€‹

// Add a reaction
app.OnMessage(async (context, cancellationToken) =>
{
await context.Send("Hello! I'll react to your message.", cancellationToken);

// Add a reaction to the incoming message
await context.Api.Conversations.Reactions.AddAsync(
context.Activity.Conversation.Id,
context.Activity.Id,
ReactionType.Like,
cancellationToken: cancellationToken
);
});

Pythonโ€‹

# Add a reaction
@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]):
await ctx.send("Hello! I'll react to your message.")

# Add a reaction to the incoming message
await ctx.api.reactions.add(
ctx.activity.conversation.id,
ctx.activity.id,
'like'
)

Removing a Reactionโ€‹

The pattern for reaction removal is standardized across languages. Below are examples of removing the ๐Ÿ‘ like reaction from a message in each language:

TypeScriptโ€‹

// Remove a reaction
app.on('message', async ({ activity, api, send }) => {
await send("Hello! I'll react to this message.");
await api.conversations.reactions.delete(activity.conversation.id, activity.id, 'like');
});

.NETโ€‹

// Remove a reaction
app.OnMessage(async context =>
{
await context.Api.Conversations.Reactions.DeleteAsync(
context.Activity.Conversation.Id,
context.Activity.Id,
new ReactionType("like")
);
})

Pythonโ€‹

# Remove a reaction
@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]):
await ctx.api.conversations.reactions.delete(
ctx.activity.conversation.id,
ctx.activity.id,
'like'
)

Listening to Reactionsโ€‹

Listening to reactions in conjunction with sending reactions can help you create complete end-to-end scenarios. In the following examples, agents listen for a ๐Ÿ‘ like reaction and take action when that reaction has been added to an agent's message:

TypeScriptโ€‹

app.on('messageReaction', async ({ activity }) => {
// Listen for a reaction added to agent message
for (const reaction of activity.reactionsAdded ?? []) {
if (reaction.type === 'like') {
// Complete some task here
}
}

// Listen for a reaction removed from agent message
for (const reaction of activity.reactionsRemoved ?? []) {
if (reaction.type === 'like') {
// Complete some task here
}
}
});

.NETโ€‹

// Listen for a reaction added to agent message
app.OnMessageReactionAdded(async (context, cancellationToken) => {
foreach (var reaction in context.Activity.ReactionsAdded ?? []) {
if (reaction.Type == "like") {
// Complete some task here
}
}
});

// Listen for a reaction removed from agent message
app.OnMessageReactionRemoved(async (context, cancellationToken) => {
foreach (var reaction in context.Activity.ReactionsRemoved ?? []) {
if (reaction.Type == "like") {
// Complete some task here
}
}
});

Pythonโ€‹

# Listen for a reaction added to agent message
@app.on_message_reaction
async def handle_reaction_added(ctx: ActivityContext[MessageReactionActivity]):
for reaction in ctx.activity.reactions_added or []:
if reaction.type == "like":
# Complete some task here
pass


# Listen for a reaction removed from agent message
@app.on_message_reaction
async def handle_reaction_removed(ctx: ActivityContext[MessageReactionActivity]):
for reaction in ctx.activity.reactions_removed or []:
if reaction.type == "like":
# Complete some task here
pass

Reaction IDs (EmojiIDs)โ€‹

When using emojis as reactions in Teams you must use the Teams specific EmojiID to identify the correct emoji you'd like to send. Below are some examples of EmojiIDs:

EmojiIDEmojiDiverse (skin tones)
like๐Ÿ‘No
heartโค๏ธNo
happyface๐Ÿ˜ŠNo
grinningfacewithsmilingeyes๐Ÿ˜„No
1f603_grinningfacewithbigeyes๐Ÿ˜ƒNo
1f44b_wavinghand๐Ÿ‘‹Yes
1f590_handwithfingerssplayed๐Ÿ–๏ธYes
1f91a_raisedbackofhand๐ŸคšYes

Skin-tone variants are supported via suffix modifiers:

  • 1f44b_wavinghand-tone1
  • 1f44b_wavinghand-tone2
  • 1f44b_wavinghand-tone3
  • 1f44b_wavinghand-tone4
  • 1f44b_wavinghand-tone5

Teams Reactions Referenceโ€‹

Alongside this preview, we're publishing the Teams Reactions Reference. This page was created as a developer resource for discovering all thevalid EmojiIDs supported by Teams.

The reference includes:

  • Complete catalog of supported EmojiIDs organized by category (Smileys, Hand gestures, etc.)
  • Skin-tone variations for diverse emojis

We're continuously adding new capabilites and features based on your feedback. We're excited to release this capability to you and can't wait to see what you build!๐ŸŽ‰