Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,27 @@ import TabItem from '@theme/TabItem';
```
</TabItem>
</Tabs>

<!-- targeted-message-example -->

<Tabs>
<TabItem label="Controller" value="controller" default>
```csharp
[Message]
public async Task OnMessage([Context] IContext.Client client)
{
// Send a private reply visible only to the sender
await client.Send("Hey! This is a private message just for you!", isTargeted: true);
}
```
</TabItem>
<TabItem label="Minimal" value="minimal">
```csharp
app.OnMessage(async context =>
{
// Send a targeted message visible only to the sender
await context.Send("Hey! This is a private message just for you!", isTargeted: true);
});
```
</TabItem>
</Tabs>
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,26 @@ public static class Notifications
await app.Send(conversationId, "Hey! It's been a while. How are you?");
}
}
```

<!-- targeted-proactive-example -->

```csharp
public static class Notifications
{
public static async Task SendProactiveTargeted(string userId)
{
var conversationId = (string?)storage.Get(userId);

if (conversationId is null) return;

// Set Recipient to specify who should receive the private message
var targetedMessage = new MessageActivity("This is a private reminder just for you!")
{
Recipient = new ChannelAccount { Id = userId }
};

await app.Send(conversationId, targetedMessage, isTargeted: true);
Copy link
Member

Choose a reason for hiding this comment

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

I think ConversationType is a required param here

}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,21 @@ async def send_proactive_notification(user_id: str):
return
activity = MessageActivityInput(text="Hey! It's been a while. How are you?")
await app.send(conversation_id, activity)
```

<!-- targeted-proactive-example -->

```python
from microsoft_teams.api import MessageActivityInput, Account
# ...

async def send_targeted_proactive_notification(user_id: str, recipient_id: str):
conversation_id = storage.get(user_id, "")
if not conversation_id:
return

activity = MessageActivityInput(text="This is a private reminder just for you!")
activity.recipient = Account(id=recipient_id, role="user")

await app.send(conversation_id, activity, is_targeted=True)
```
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,24 @@ const sendProactiveNotification = async (userId: string) => {
const activity = new MessageActivity('Hey! It\'s been a while. How are you?');
await app.send(conversationId, activity);
};
```

<!-- targeted-proactive-example -->

```typescript
import { MessageActivity, Account } from '@microsoft/teams.api';
import { App } from '@microsoft/teams.apps';
// ...

const sendTargetedProactiveNotification = async (userId: string, recipientId: string) => {
const conversationId = myConversationIdStorage.get(userId);
if (!conversationId) {
return;
}

const activity = new MessageActivity('This is a private reminder just for you!');
activity.recipient = { id: recipientId, role: 'user' } as Account;

await app.send(conversationId, activity, true);
};
```
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,12 @@ async def handle_message(ctx: ActivityContext[MessageActivity]):
async def handle_message(ctx: ActivityContext[MessageActivity]):
await ctx.send(MessageActivityInput(text='hi!').add_mention(account=ctx.activity.from_))
```

<!-- targeted-message-example -->

```python
@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]):
# Send a targeted message that only the sender can see
await ctx.send('This message is only visible to you!', is_targeted=True)
```
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,12 @@ app.on('message', async ({ send, activity }) => {
await send(new MessageActivity('hi!').addMention(activity.from));
});
```

<!-- targeted-message-example -->

```typescript
app.on('message', async ({ send, activity }) => {
// Send a targeted message that only the sender can see
await send('This message is only visible to you!', undefined, true);
});
```
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ summary: Guide to sending messages from your Teams SDK agent, including replies,
title: Sending Messages
---

import Language from '@site/src/components/Language';

# Sending Messages

Sending messages is a core part of an agent's functionality. With all activity handlers, a `send` method is provided which allows your handlers to send a message back to the user to the relevant conversation.
Expand Down Expand Up @@ -37,3 +39,28 @@ Streaming is currently only supported in 1:1 conversations, not group chats or c
Sending a message at `@mentions` a user is as simple including the details of the user using the <LanguageInclude section="mention-method-name" /> method

<LanguageInclude section="mention-example" />

## Targeted Messages

:::info Preview Feature
Targeted messages are currently in preview.
:::

Targeted messages allow you to send messages privately to a specific recipient in a conversation.
To send a targeted message, use the `isTargeted` parameter in your `send` method:

<LanguageInclude section="targeted-message-example" />

<Language language="csharp">

## Errors

The following table lists errors that may be returned when sending messages.

| Error | Description |
|-------|-------------|
| `InvalidOperationException`<br/>`app not started` | The app has not been started. Call `await app.Start()` before sending messages or using proactive messaging. |
| `ArgumentException`<br/>`activity.Recipient is required for targeted messages` | When using `isTargeted: true`, the `Recipient` property must be set on the activity to specify who should receive the private message. |
| `Exception`<br/>`no plugin that can send activities was found` | No sender plugin is configured. Ensure a sender plugin (like AspNetCorePlugin) is added to the app. |

</Language>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ title: 'Proactive Messaging'
summary: Learn how to send proactive messages to users without waiting for them to initiate the conversation, including storing conversation IDs and sending notifications.
---

import Language from '@site/src/components/Language';

# Proactive Messaging

In [Sending Messages](./), you were shown how to respond to an event when it happens. However, there are times when you want to send a message to the user without them sending a message first. This is called proactive messaging. You can do this by using the `send` method in the `app` instance. This approach is useful for sending notifications or reminders to the user.
Expand All @@ -20,3 +22,17 @@ Then, when you want to send a proactive message, you can retrieve the <LanguageI
:::tip
In this example, you see how to get the <LanguageInclude section="conversation-id-field" /> using one of the activity handlers. This is a good place to store the conversation id, but you can also do this in other places like when the user installs the app or when they sign in. The important thing is that you have the conversation id stored somewhere so you can use it later.
:::

## Targeted Proactive Messages

:::info Preview Feature
Targeted proactive messages are currently in preview.
:::

You can also send [targeted messages](./#targeted-messages) proactively to deliver private messages to a specific user in a conversation.

:::info Requirements
- Recipient property must be set on the activity when using targeted messages
:::

<LanguageInclude section="targeted-proactive-example" />