Enviar notificações proativas para os usuários
APLICA-SE A: SDK v4
Normalmente, um bot envia uma mensagem para um usuário diretamente em resposta ao recebimento de uma mensagem do usuário. Ocasionalmente, um bot pode precisar enviar uma mensagem proativa, uma mensagem em resposta a estímulos que não se originam do usuário.
Mensagens proativas podem ser útil em uma variedade de cenários. Por exemplo, se o usuário tiver solicitado ao bot o monitoramento do preço de um produto, se o preço do produto cair 20%, o bot poderá alertar o usuário. Ou, se o bot precisar de um tempo para compilar uma resposta para a pergunta do usuário, ele poderá informar ao usuário sobre o atraso e permitir que a conversa continue enquanto isso. Quando o bot terminar de compilar a resposta para a pergunta, compartilhará essas informações com o usuário.
Observação
Este artigo aborda informações sobre mensagens proativas para bots em geral. Para obter informações sobre mensagens proativas no Microsoft Teams, consulte
- O Teams exemplo de bot de conversa em C#, JavaScript, Java ou Python.
- O Microsoft Teams documentação sobre como enviar mensagens proativas.
Pré-requisitos
- Entenda sobre as Noções básicas do bot.
- Uma cópia do exemplo de mensagens proativas em C#, JavaScript, Java ou Python. O exemplo é usado para explicar sobre mensagens proativas neste artigo.
Sobre a amostra proativa
Em geral, um bot como aplicativo tem algumas camadas:
- O aplicativo Web que pode aceitar solicitações HTTP e dá suporte especificamente a um ponto de extremidade de mensagens.
- Um adaptador que manipula a conectividade com os canais.
- Um manipulador para a vez, normalmente encapsulado em uma classe de bot que manipula o raciocínio de conversa para o aplicativo bot.
Em resposta a uma mensagem de entrada do usuário, o aplicativo chama o método de atividade de processo do adaptador, que cria um contexto de turno e turno, chama seu pipeline de middleware e, em seguida, chama o manipulador de turnos do bot.
Para iniciar uma mensagem proativa, o aplicativo bot precisa ser capaz de receber entrada adicional. A lógica do aplicativo para iniciar uma mensagem proativa está fora do escopo do SDK. Para este exemplo, um ponto de extremidade de notificação , além de um ponto de extremidade de mensagens padrão, é usado para disparar a virada proativa.
Em resposta a uma solicitação GET neste ponto de extremidade de notificação, o aplicativo chama o método de conversa contínua do adaptador, que se comporta de forma semelhante ao método de atividade do processo . O método de conversa de continuação :
- Usa uma referência de conversa apropriada para o usuário e o método de retorno de chamada a ser usado para o turno proativo.
- Cria uma atividade de evento e transforma o contexto para a virada proativa.
- Chama o pipeline de middleware do adaptador.
- Chama o método de retorno de chamada fornecido.
- O contexto de turno usa a referência de conversa para enviar mensagens ao usuário.
O exemplo tem um bot, um ponto de extremidade de mensagens e um ponto de extremidade de notificação adicional que é usado para enviar mensagens proativas ao usuário, conforme mostrado na ilustração a seguir.

Recuperar e armazenar a referência de conversa
Quando o Bot Framework Emulator se conecta ao bot, o bot recebe duas atividades de atualização de conversa. No manipulador de atividade de atualização de conversa do bot, a referência de conversa é recuperada e armazenada em um dicionário, conforme mostrado abaixo.
Bots\ProactiveBot.cs
private void AddConversationReference(Activity activity)
{
var conversationReference = activity.GetConversationReference();
_conversationReferences.AddOrUpdate(conversationReference.User.Id, conversationReference, (key, newValue) => conversationReference);
}
protected override Task OnConversationUpdateActivityAsync(ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
AddConversationReference(turnContext.Activity as Activity);
return base.OnConversationUpdateActivityAsync(turnContext, cancellationToken);
}
A referência de conversa inclui uma propriedade de conversa que descreve a conversa na qual a atividade existe. A conversa inclui uma propriedade do usuário que lista os usuários que participam da conversa e uma propriedade de URL de serviço que indica para onde as respostas à atividade atual podem ser enviadas. Uma referência de conversa válida é necessária para enviar mensagens proativas para os usuários. (Para o canal Teams, a URL de serviço é mapeada para um servidor regionalizado.)
Observação
Em um cenário real, você manteria as referências de conversa em um banco de dados em vez de usar um objeto na memória.
Enviar uma mensagem proativa
O segundo controlador, o controlador de notificação , é responsável por enviar a mensagem proativa ao usuário. Ele usa as etapas a seguir para gerar uma mensagem proativa.
- Recupera a referência da conversa para a qual enviar a mensagem proativa.
- Chama o método de conversa contínua do adaptador, fornecendo a referência de conversa e o delegado do manipulador de turno a ser usado. (O método de conversa continuação gera um contexto de turno para a conversa referenciada e, em seguida, chama o delegado do manipulador de turno especificado.)
- No delegado, usa o contexto de turno para enviar a mensagem proativa. Aqui, o delegado é definido no controlador de notificação e envia a mensagem proativa para o usuário.
Observação
Embora cada canal deva usar uma URL de serviço estável, a URL pode ser alterada ao longo do tempo. Para obter mais informações sobre a URL de serviço, consulte a estrutura de atividades básicas e as seções de URL de serviço do Esquema de Atividade do Bot Framework.
Se a URL do serviço for alterada, as referências de conversa anteriores não serão mais válidas e as chamadas para continuar a conversa gerarão um erro ou exceção. Nesse caso, o bot precisará adquirir uma nova referência de conversa para o usuário antes que ele possa enviar mensagens proativas novamente.
Controllers\NotifyController .cs
Sempre que a página de notificação do bot é solicitada, o controlador de notificação recupera as referências de conversa a partir do dicionário.
Então, o controlador usa os métodos ContinueConversationAsync e BotCallback para enviar a mensagem proativa.
[Route("api/notify")]
[ApiController]
public class NotifyController : ControllerBase
{
private readonly IBotFrameworkHttpAdapter _adapter;
private readonly string _appId;
private readonly ConcurrentDictionary<string, ConversationReference> _conversationReferences;
public NotifyController(IBotFrameworkHttpAdapter adapter, IConfiguration configuration, ConcurrentDictionary<string, ConversationReference> conversationReferences)
{
_adapter = adapter;
_conversationReferences = conversationReferences;
_appId = configuration["MicrosoftAppId"] ?? string.Empty;
}
public async Task<IActionResult> Get()
{
foreach (var conversationReference in _conversationReferences.Values)
{
await ((BotAdapter)_adapter).ContinueConversationAsync(_appId, conversationReference, BotCallback, default(CancellationToken));
}
// Let the caller know proactive messages have been sent
return new ContentResult()
{
Content = "<html><body><h1>Proactive messages have been sent.</h1></body></html>",
ContentType = "text/html",
StatusCode = (int)HttpStatusCode.OK,
};
}
private async Task BotCallback(ITurnContext turnContext, CancellationToken cancellationToken)
{
await turnContext.SendActivityAsync("proactive hello");
}
}
Para enviar uma mensagem proativa, o adaptador requer uma ID do aplicativo para o bot. Em um ambiente de produção, você pode usar a ID do aplicativo do bot. Para testar o bot localmente com o Emulator, você pode usar a cadeia de caracteres vazia ("").
Testar seu bot
- Se ainda não tiver feito isso, instale o Bot Framework Emulator.
- Execute o exemplo localmente em seu computador.
- Inicie o Emulator e conecte-se ao bot.
- Carregar à página de api/notificação do seu bot. Isso gerará uma mensagem proativa no Emulator.
Informações adicionais
Além do exemplo usado neste artigo, exemplos adicionais estão disponíveis em GitHub.
Requisitos
Antes de enviar uma mensagem proativa, o bot precisa de uma referência de conversa. Seu bot pode recuperar a referência de conversa de qualquer atividade recebida do usuário, mas isso normalmente exige que o usuário interaja com o bot pelo menos uma vez antes que o bot possa enviar uma mensagem proativa.
Muitos canais proíbem um bot de enviar mensagens a um usuário, a menos que o usuário tenha mensagem do bot pelo menos uma vez. Alguns canais permitem exceções. Por exemplo, o canal Teams permite que o bot envie uma mensagem proativa (ou 1 contra 1) para indivíduos em uma conversa em grupo já estabelecida que inclui o bot.
Considerações sobre o design
Ao implementar mensagens proativas em seu bot, não envie várias mensagens proativas em um curto período de tempo. Alguns canais impõem restrições sobre a frequência de envio de mensagens para o usuário de um bot, e desabilitarão o bot se ele violar essas restrições.
Uma mensagem proativa ad hoc é o tipo mais simples de mensagem proativa. O bot apenas injeta a mensagem na conversa sempre que ele é disparado, sem considerar se o usuário está envolvido em um tópico separado de conversa com o bot e não tentará alterar a conversa de modo algum.
Para lidar com notificações de forma mais suave, considere outras maneiras de integrar a notificação no fluxo de conversa, como definir um sinalizador no estado da conversa ou adicionar a notificação a uma fila.
Sobre a virada proativa
O método de conversa continuação usa a referência de conversa e um manipulador de retorno de chamada para:
- Crie uma curva na qual o aplicativo bot pode enviar a mensagem proativa. O adaptador cria uma
eventatividade para essa vez, com seu nome definido como "ContinueConversation". - Envie a curva por meio do pipeline de middleware do adaptador.
- Chame o manipulador de retorno de chamada de turno para executar a lógica personalizada.
No exemplo de mensagens proativas , o manipulador de retorno de chamada de turno é definido no controlador de notificação e envia a mensagem diretamente para a conversa, sem enviar a atividade proativa por meio do manipulador de turno normal do bot. O código de exemplo também não acessa nem atualiza o estado do bot na curva proativa.
Muitos bots têm estado e usam o estado para gerenciar uma conversa em várias voltas. Quando o método de conversa continuar cria um contexto de turno, a curva terá o estado correto do usuário e da conversa associados a ele e você pode integrar transformações proativas na lógica do bot. Se você precisar que a lógica do bot esteja ciente da mensagem proativa, terá algumas opções para fazer isso. Você poderá:
- Forneça o manipulador de turnos do bot como o manipulador de retorno de chamada de turno. Em seguida, o bot receberá a atividade de evento "ContinueConversation".
- Use o manipulador de retorno de chamada de turno para adicionar informações primeiro ao contexto de turno e, em seguida, chamar o manipulador de turno do bot.
Em ambos os casos, você precisará projetar sua lógica de bot para lidar com o evento proativo.