Tener una conversación con un bot de Microsoft Teams

Importante

Este artículo se basa en el SDK de Bot Framework v3. Si busca la versión 4.6 o posterior de la documentación actual del SDK, consulte la sección bots conversacionales .

Una conversación es una serie de mensajes enviados entre el bot y uno o más usuarios. Hay tres tipos de conversaciones (también denominadas ámbitos) en Teams:

  • teams: también denominadas conversaciones de canal, visibles para todos los miembros del canal
  • personal: conversaciones entre bots y un único usuario
  • groupChat Chat entre un bot y dos o más usuarios.

Un bot se comporta de modo ligeramente diferente según el tipo de conversación en la que participe:

Para que el bot funcione en un ámbito determinado, debe aparecer como compatible con ese ámbito en el manifiesto. Los ámbitos se definen y se describen más detalladamente en la Referencia del Manifiesto.

Mensajes proactivos

Los bots pueden participar en una conversación o iniciar una. La mayor parte de la comunicación es en respuesta a otro mensaje. Si un bot inicia una conversación, se denomina mensaje proactivo. Algunos ejemplos son:

  • Mensajes de bienvenida
  • Notificaciones de eventos
  • Sondeo de mensajes

Conceptos básicos de la conversación

Cada mensaje es un objeto Activity de tipo messageType: message. Cuando un usuario envía un mensaje, Teams publica el mensaje en el bot; en concreto, envía un objeto JSON al punto de conexión de mensajería del bot. El bot examina el mensaje para determinar su tipo y responder correctamente.

Los bots también admiten mensajes de estilo de evento. Para obtener más información, vea Manejo de eventos de bot en Microsoft Teams. Actualmente no se admite la voz.

Los mensajes suelen ser los mismos en todos los ámbitos, pero hay diferencias en cómo se accede al bot desde la interfaz de usuario y diferencias en segundo plano, que debe conocer.

La conversación básica se controla a través de Bot Framework Connector, una única API REST para permitir que el bot se comunique con Teams y otros canales. El SDK de Bot Builder proporciona acceso sencillo a esta API, funcionalidad adicional para administrar el flujo y el estado de la conversación y formas sencillas de incorporar servicios cognitivos, como el procesamiento de lenguaje natural (NLP).

Contenido del mensaje

El bot puede enviar texto enriquecido, imágenes y tarjetas. Los usuarios pueden enviar texto enriquecido e imágenes al bot. Puede especificar el tipo de contenido que el bot puede controlar en la página de configuración de Microsoft Teams del bot.

Formato De usuario a bot De bot a usuario Notas
Texto enriquecido
Imágenes Máximo 1024x1024 y 1 MB en formato PNG, JPEG o GIF. No se admiten GIF animados.
Tarjetas Consulte la Referencia de Tarjetas de Teams para ver las tarjetas admitidas.
Emojis Teams admite actualmente emojis a través de UTF-16, como U+1F600 para la cara sonriente.

Para obtener más información sobre los tipos de interacción de bots admitidos por el Bot Framework, en los que se basan los bots de los equipos, consulte la documentación Bot Framework sobre flujo de la conversación y los conceptos relacionados en la documentación de el Bo Builder de SDK para .NET y el Bot Builder de SDK para Node.js.

Formato de mensajes

Puede establecer la propiedad opcional TextFormat de un message para controlar cómo se representa el contenido de texto del mensaje. Consulte Formato de mensajes para obtener una descripción detallada del formato admitido en los mensajes del bot. Puede establecer la propiedad opcional TextFormat para controlar cómo se representa el contenido de texto del mensaje.

Para obtener información detallada sobre cómo Teams admite el formato de texto en teams, vea Formateo de texto en mensajes de bot.

Para obtener más información sobre cómo dar formato a tarjetas en mensajes, vea Formato de tarjetas.

Mensajes de imagen

Las imágenes se envían agregando datos adjuntos a un mensaje. Puede encontrar más información sobre los datos adjuntos en la Bot Framework documentación.

Las imágenes pueden tener como máximo 1024×1024 MB y 1 MB en formato PNG, JPEG o GIF; GIF animado no se admite.

Se recomienda especificar el alto y el ancho de cada imagen mediante XML. Si usa Markdown, el tamaño predeterminado de la imagen es 256>256. Por ejemplo:

  • Use <img src="http://aka.ms/Fo983c" alt="Duck on a rock" height="150" width="223"></img>
  • No usar ![Duck on a rock](http://aka.ms/Fo983c)

Recepción de mensajes

En función de los ámbitos que se declaren, el bot puede recibir mensajes en los contextos siguientes:

  • chat personal Los usuarios pueden interactuar en una conversación privada con un bot si seleccionan el bot que se ha agregado en el historial de chats o escribiendo el nombre o id. de aplicación en el cuadro Para: en un nuevo chat.
  • Channels Se puede mencionar un bot ("@nombredelbot") en un canal si se ha agregado al equipo. Tenga en cuenta que las respuestas adicionales a un bot en un canal requieren mencionar el bot. No responderá si no se le ha mencionado en las respuestas.

Para los mensajes entrantes, el bot recibe un objeto Activity de tipo messageType: message. Aunque el objeto Activity puede contener otros tipos de información, al igual que actualizaciones de canal enviadas al bot, el tipo message representa la comunicación entre el bot y el usuario.

El bot recibe una carga que contiene el mensaje Text de usuario y otra información sobre el usuario, el origen del mensaje y la información de Teams. Nota:

  • timestamp La fecha y hora del mensaje en hora universal coordinada (UTC).
  • localTimestamp La fecha y hora del mensaje en la zona horaria del remitente.
  • channelId Siempre "msteams". Esto hace referencia a un canal de Bot Framework, no a un canal de teams.
  • from.id un identificador único y cifrado para ese usuario para el bot; adecuado como clave si la aplicación necesita almacenar datos de usuario. Es único para el bot y no se puede usar directamente fuera de la instancia del bot de ninguna manera para identificar a ese usuario.
  • channelData.tenant.id El identificador de espacio empresarial del usuario.

Nota:

from.id es único para el bot y no se puede usar directamente fuera de la instancia del bot de ninguna manera significativa para identificar a ese usuario.

Combinación de interacciones de canal y privadas con el bot

Al interactuar en un canal, el bot debe ser inteligente para desconectar determinadas conversaciones con un usuario. Por ejemplo, supongamos que un usuario está intentando coordinar una tarea compleja, como la programación con un conjunto de miembros del equipo. En lugar de hacer que toda la secuencia de interacciones sea visible para el canal, considere la posibilidad de enviar un mensaje de chat personal al usuario. El bot debería poder realizar fácilmente la transición del usuario entre conversaciones personales y de canal sin perder el estado.

Nota:

No olvide actualizar el canal cuando se complete la interacción para notificar a los demás miembros del equipo.

Ejemplo de esquema de entrada completa

{
    "type": "message",
    "id": "1485983408511",
    "timestamp": "2017-02-01T21:10:07.437Z",
    "localTimestamp": "2017-02-01T14:10:07.437-07:00",
    "serviceUrl": "https://smba.trafficmanager.net/amer/",
    "channelId": "msteams",
    "from": {
        "id": "29:1XJKJMvc5GBtc2JwZq0oj8tHZmzrQgFmB39ATiQWA85gQtHieVkKilBZ9XHoq9j7Zaqt7CZ-NJWi7me2kHTL3Bw",
        "name": "Megan Bowen",
        "aadObjectId": "7faf8ab2-3d56-4244-b585-20c8a42ed2b8"
    },
    "conversation": {
        "conversationType": "personal",
        "id": "a:17I0kl9EkpE1O9PH5TWrzrLNwnWWcfrU7QZjKR0WSfOpzbfcAg2IaydGElSo10tVr4C7Fc6GtieTJX663WuJCc1uA83n4CSrHSgGBj5XNYLcVlJAs2ZX8DbYBPck201w-"
    },
    "recipient": {
        "id": "28:c9e8c047-2a74-40a2-b28a-b162d5f5327c",
        "name": "Teams TestBot"
    },
    "textFormat": "plain",
    "text": "Hello Teams TestBot",
    "entities": [
      { 
        "locale": "en-US",
        "country": "US",
        "platform": "Windows",
        "timezone": "America/Los_Angeles",
        "type": "clientInfo"
      }
    ],
    "channelData": {
        "tenant": {
            "id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
        }
    },
    "locale": "en-US"
}

Nota:

El campo de texto para los mensajes entrantes a veces contiene menciones. Asegúrese de comprobarlos y quitarlos correctamente. Para obtener más información, consulte Menciones.

Datos del canal de Teams

El objeto channelData contiene información específica de Teams y es el origen definitivo de los identificadores de equipo y canal. Debe almacenar en caché y usar los id. como claves para el almacenamiento local.

Un objeto channelData típico de una actividad enviada al bot contiene la siguiente información:

  • eventType Tipo de evento de Teams; se pasa solo en los casos de eventos de modificación de canal.
  • tenant.idMicrosoft Entra identificador de inquilino; se pasa en todos los contextos.
  • team Solo se pasa en contextos de canal, no en chat personal.
  • channel Solo se pasa en contextos de canal cuando se menciona el bot o para eventos en canales de equipos en los que se ha agregado el bot.
  • channelData.teamsTeamId En desuso Esta propiedad solo se incluye por compatibilidad con versiones anteriores.
  • channelData.teamsChannelId En desuso Esta propiedad solo se incluye por compatibilidad con versiones anteriores.

Ejemplo de objeto channelData (evento channelCreated)

"channelData": {
    "eventType": "channelCreated",
    "tenant": {
        "id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
    },
    "channel": {
        "id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype",
        "name": "My New Channel"
    },
    "team": {
        "id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype"
    }
}

Ejemplo de .NET

El paquete NuGet Microsoft.Bot.Connector.Teams proporciona un objeto TeamsChannelData especializado, que expone propiedades para acceder a información específica de Teams.

TeamsChannelData channelData = activity.GetChannelData<TeamsChannelData>();
string tenantId = channelData.Tenant.Id;

Envío de respuestas a mensajes

Para responder a un mensaje existente, llame a ReplyToActivity en .NET o session.senden Node.js. El Bot Builder de SDK controla todos los detalles.

Si decide usar la API rest, también puede llamar al punto de conexión /v3/conversations/{conversationId}/activities/{activityId}.

El propio contenido del mensaje puede contener texto simple o algunos de los Bot Framework proporcionados tarjetas y acciones de tarjeta.

Tenga en cuenta que en el esquema de salida siempre debe usar el mismo serviceUrl que el que recibió. Tenga en cuenta que el valor de serviceUrl tiende a ser estable, pero puede cambiar. Cuando llega un mensaje nuevo, el bot debe comprobar su valor almacenado de serviceUrl.

Actualizando mensaje...

En lugar de que los mensajes sean instantáneas estáticas de datos, el bot puede actualizar dinámicamente los mensajes insertados después de enviarlos. Puede usar actualizaciones de mensajes dinámicos para escenarios como las actualizaciones de sondeo, la modificación de las acciones disponibles después de presionar un botón o cualquier otro cambio de estado asincrónico.

El nuevo mensaje no tiene que coincidir con el original en el tipo. Por ejemplo, si el mensaje original contenía datos adjuntos, el nuevo mensaje puede ser un mensaje de texto.

Nota:

Solo puede actualizar el contenido enviado en mensajes de datos adjuntos únicos y diseños de carrusel. No se admite la publicación de actualizaciones en mensajes con varios datos adjuntos en el diseño de lista.

API de REST

Para emitir una actualización de mensajes, realice una solicitud PUT en el punto de /v3/conversations/<conversationId>/activities/<activityId>/ conexión mediante un identificador de actividad determinado. Para completar este escenario, debe almacenar en caché el identificador de actividad devuelto por la llamada POST original.

PUT /v3/conversations/19%3Aja0cu120i1jod12j%40skype.net/activities/012ujdo0128
{
    "type": "message",
    "text": "This message has been updated"
}

Ejemplo de .NET

Puede usar el método UpdateActivityAsync en el SDK de Bot Builder para actualizar un mensaje existente.

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
  if (activity.Type == ActivityTypes.Message)
  {
    ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
    Activity reply = activity.CreateReply($"You sent {activity.Text} which was {activity.Text.Length} characters");
    var msgToUpdate = await connector.Conversations.ReplyToActivityAsync(reply);
    Activity updatedReply = activity.CreateReply($"This is an updated message");
    await connector.Conversations.UpdateActivityAsync(reply.Conversation.Id, msgToUpdate.Id, updatedReply);
  }
}

Ejemplo de Node.js

Puede usar el método session.connector.update en el SDK de Bot Builder para actualizar un mensaje existente.

function sendCardUpdate(bot, session, originalMessage, address) {

  var origAttachment = originalMessage.data.attachments[0];
  origAttachment.content.subtitle = 'Assigned to Larry Jin';

  var updatedMsg = new builder.Message()
    .address(address)
    .textFormat(builder.TextFormat.markdown)
    .addAttachment(origAttachment)
    .toMessage();

  session.connector.update(updatedMsg, function(err, addresses) {
    if (err) {
      console.log(`Could not update the message`);
    }
  });
}

Iniciar una conversación (mensajería proactiva)

Puede crear una conversación personal con un usuario o iniciar una nueva cadena de respuestas en un canal para el bot de equipo. Esto le permite enviar un mensaje al usuario o a los usuarios sin que hayan iniciado el contacto con el bot. Para más información, consulte los siguientes artículos:

Para obtener más información sobre las conversaciones iniciadas por los bots, consulte Mensajería proactiva para bots.

Eliminar mensajes

Los mensajes se pueden eliminar mediante el connector.delete() método del SDK de BotBuilder.

bot.dialog('BotDeleteMessage', function (session: builder.Session) {
  var msg = new teams.TeamsMessage(session).text("Bot will delete this message in 5 sec.")
  bot.send(msg, function (err, response) {
    if (err) {
      console.log(err);
      session.endDialog();
    }

    console.log('Proactive message response:');
    console.log(response);
    console.log('---------------------------------------------------')
    setTimeout(function () {
      var activityId: string = null;
      var messageAddress: builder.IChatConnectorAddress = null;
      if (response[0]){
        messageAddress = response[0];
        activityId = messageAddress.id;
      }

      if (activityId == null)
      {
        console.log('Message failed to send.');
        session.endDialog();
        return;
      }

      // Bot delete message
      let address: builder.IChatConnectorAddress  = {
        channelId: 'msteams',
        user: messageAddress.user,
        bot: messageAddress.bot,
        id : activityId,
        serviceUrl : (<builder.IChatConnectorAddress>session.message.address).serviceUrl,
        conversation: {
          id: session.message.address.conversation.id
        }
      };

      connector.delete(address, function (err) {
        if (err)
        {
          console.log(err);
        }
        else
        {
          console.log("Message: " + activityId + " deleted successfully.");
        }

        // Try editing deleted message would fail
        var newMsg = new builder.Message().address(address).text("To edit message.");
        connector.update(newMsg.toMessage(), function (err, address) {
          if (err)
          {
            console.log(err);
            console.log('Deleted message can not be edited.');
          }
          else
          {
            console.log("There is something wrong. Message: " + activityId + " edited successfully.");
            console.log(address);
          }

          session.endDialog();
        });
      });
    }, 5000);
  });
})