Envío de notificaciones activas a los usuarios

SE APLICA A: SDK v4

Normalmente, un bot envía un mensaje a un usuario directamente en respuesta a recibir un mensaje del usuario. En ocasiones, un bot podría necesitar enviar un mensaje proactivo, un mensaje en respuesta al estímulo que no se origina en el usuario.

Los mensajes proactivos pueden ser útiles en diversos escenarios. Por ejemplo, si el usuario ha solicitado anteriormente al bot que supervise el precio de un producto, el bot puede alertar al usuario si el precio del producto ha descendido un 20 %. O bien, si un bot necesita algo de tiempo para compilar una respuesta a la pregunta del usuario, puede informar al usuario del retraso y permitir que la conversación continúe mientras tanto. Cuando el bot termine de compilar la respuesta a la pregunta, compartirá esta información con el usuario.

En este artículo se describe información sobre los mensajes proactivos para los bots en general. Para obtener información sobre los mensajes proactivos en Microsoft Teams, consulte

Nota:

Los SDK de JavaScript, C# y Python de Bot Framework seguirán siendo compatibles, pero el SDK de Java se va a retirar con la finalización del soporte técnico a largo plazo en noviembre de 2023. Solo se realizarán correcciones de errores y seguridad críticos en este repositorio.

Los bots existentes creados con el SDK de Java seguirán funcionando.

Para la nueva compilación de bots, considere la posibilidad de usar Power Virtual Agents y lea sobre cómo elegir la solución de bot de chat adecuada.

Para obtener más información, consulte El futuro de la construcción de bots.

Requisitos previos

Acerca del ejemplo proactivo

En general, un bot como una aplicación tiene algunas capas:

  • La aplicación web que puede aceptar solicitudes HTTP y que admite específicamente un punto de conexión de mensajería.
  • Un adaptador que controla la conectividad con los canales.
  • Un controlador para el turno, normalmente encapsulado en una clase de bot que controla el razonamiento conversacional de la aplicación de bot.

En respuesta a un mensaje entrante del usuario, la aplicación llama al método de actividad de proceso del adaptador, que crea un contexto de turno y turno, llama a su canalización de middleware y, a continuación, llama al controlador de turnos del bot.

Para iniciar un mensaje proactivo, la aplicación de bot debe poder recibir otra entrada. La lógica de aplicación para iniciar un mensaje proactivo está fuera del ámbito del SDK. En este ejemplo, se usa un punto de conexión de notificación, además de un punto de conexión de mensajes estándar, para desencadenar el turno proactivo.

En respuesta a una solicitud GET en este punto de conexión de notificación, la aplicación llama al método continue conversation del adaptador, que se comporta de forma similar al método de actividad de proceso. El método continue conversation:

  • Toma una referencia de conversación adecuada para el usuario y el método de devolución de llamada que se va a usar para el turno proactivo.
  • Crea una actividad de evento y un contexto de turno para el turno proactivo.
  • Llama a la canalización de middleware del adaptador.
  • Llama al método de devolución de llamada proporcionado.
  • El contexto de turno usa la referencia de conversación para enviar mensajes al usuario.

El ejemplo tiene un bot, un punto de conexión de mensajes y un punto de conexión adicional que se utiliza para enviar mensajes proactivos al usuario, como se muestra en la siguiente ilustración.

Interaction diagram showing how the bot gets a conversation reference and uses it to send a proactive message.

Recuperación y almacenamiento de la referencia de la conversación

Cuando Bot Framework Emulator se conecta al bot, este recibe dos actividades de actualización de conversación. En el controlador de actividad de actualización de conversación del bot, la referencia de la conversación se recupera y almacena en un diccionario, como se muestra a continuación.

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);
}

La referencia de la conversación incluye una propiedad conversation que describe la conversación en el que existe la actividad. La conversación incluye una propiedad user que enumera los usuarios que participan en la conversación, y una propiedad service URL que los canales usan para indicar la dirección URL que indica dónde se pueden enviar las respuestas a la actividad actual. Para enviar mensajes proactivos a los usuarios se necesita una referencia de conversación válida. (Para el canal de Teams, la dirección URL del servicio se asigna a un servidor regionalizado).

Nota:

En un escenario real, las referencias de conversación persistirían en una base de datos, en lugar de usar un objeto en memoria.

Enviar mensajes proactivos

El segundo controlador, notificar, es responsable de enviar el mensaje proactivo al usuario. Siga estos pasos para generar un mensaje proactivo.

  1. Recupera la referencia de la conversación a la que va a enviar el mensaje proactivo.
  2. Llame al método para continuar la conversación del adaptador, que proporciona la referencia de la conversación y el delegado de control de turnos que se va a usar. El método continuar conversación genera un contexto de turnos para la conversación a la que se hace referencia y, después, llama al delegado del controlador de turnos especificado.
  3. En el delegado, use el contexto de turnos para enviar el mensaje proactivo. Aquí, el delegado se define en el controlador de notificación y envía el mensaje proactivo al usuario.

Nota:

Aunque cada canal debe usar una dirección URL de servicio estable, la dirección URL puede cambiar con el tiempo. Para obtener más información sobre la dirección URL del servicio, consulte las secciones Estructura de actividad básica y Dirección URL del servicio del esquema de actividad de Bot Framework.

Si cambia la dirección URL del servicio, las referencias de conversación anteriores ya no serán válidas y las llamadas para continuar la conversación generarán un error o una excepción. En este caso, el bot tendrá que adquirir una nueva referencia de conversación para el usuario antes de poder enviar mensajes proactivos de nuevo.

Controllers\NotifyController .cs

Cada vez que se solicita la página de notificación del bot, el controlador de notificación recupera las referencias de conversación del diccionario. Luego, el controlador usa los métodos ContinueConversationAsync y BotCallback para enviar el mensaje proactivo.

[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 un mensaje proactivo, el adaptador requiere un identificador de la aplicación para el bot. En un entorno de producción, puede usar el identificador de la aplicación del bot. Para probar el bot localmente con Emulator, puede usar la cadena vacía ("").

Pruebe su bot

  1. Si aún no lo ha hecho, instale Bot Framework Emulator.
  2. Ejecute el ejemplo localmente en la máquina.
  3. Inicie el emulador y conéctelo al bot.
  4. Cargue la página de api o notificación del bot. De esa forma se generará un mensaje proactivo en el emulador.

Información adicional

Requisitos

Para poder enviar un mensaje proactivo, el bot necesita una referencia de conversación. El bot puede recuperar la referencia de conversación de cualquier actividad que haya recibido del usuario, pero normalmente requiere que el usuario interactúe con el bot al menos una vez antes de que el bot pueda enviar un mensaje proactivo.

Muchos canales prohíben a un bot enviar mensajes a un usuario a menos que el usuario haya enviado mensajes al bot al menos una vez. Algunos canales permiten excepciones. Por ejemplo, el canal de Teams permite al bot enviar un mensaje proactivo (o 1 a 1) a los usuarios de una conversación de grupo ya establecida que incluya el bot.

Consideraciones de diseño

Al implementar mensajes proactivos en un bot, no enviar varios mensajes proactivos en un breve lapso de tiempo. Algunos canales imponen restricciones sobre la frecuencia con que un bot puede enviar mensajes al usuario, y deshabilitarán el bot si se infringen tales restricciones.

Para el tipo más sencillo de mensaje proactivo, el bot intercala el mensaje en la conversación cuando se desencadene, sin tener en cuenta el estado actual o el tema de la conversación. En este escenario, el mensaje proactivo interrumpe el flujo normal de conversación.

Para controlar las notificaciones más fácilmente, considere otras formas de integrar la notificación en el flujo de conversación, como establecer una marca en el estado de la conversación o agregar la notificación a una cola.

Acerca del turno proactivo

El método continue conversation usa la referencia de conversación y un controlador de devolución de llamada para:

  1. Cree un turno en el que la aplicación de bot pueda enviar el mensaje proactivo. El adaptador crea una actividad event para este turno, con su nombre establecido en "ContinueConversation".
  2. Envíe el turno a través de la canalización de middleware del adaptador.
  3. Llame al controlador de devolución de llamada de turno para realizar lógica personalizada.

En el ejemplo de mensajes proactivos, el controlador de devolución de llamada de turno se define en el controlador de notificación y envía el mensaje directamente a la conversación, sin enviar la actividad proactiva a través del controlador de turnos normal del bot. El código de ejemplo tampoco tiene acceso ni actualiza el estado del bot en el turno proactivo.

Muchos bots tienen estado y usan el estado para administrar una conversación en varios turnos. Cuando el método continue conversation crea un contexto de turno, el turno tendrá el estado correcto del usuario y la conversación asociados, y puede integrar los cambios proactivos en la lógica del bot. Si necesita que la lógica del bot tenga en cuenta el mensaje proactivo, tiene algunas opciones para hacerlo. Puede:

  • Proporcione el controlador de turnos del bot como controlador de devolución de llamada de turno. A continuación, el bot recibirá la actividad de eventos "ContinueConversation".
  • Use el controlador de devolución de llamada de turno para agregar información al contexto de turno primero y, a continuación, llame al controlador de turnos del bot.

En ambos casos, deberá diseñar la lógica del bot para controlar el evento proactivo.

Pasos siguientes