Tener una conversación con un bot de Microsoft Teams

Importante

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

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

  • teams También se denominan conversaciones de canal, visibles para todos los miembros del canal.
  • personal Conversaciones entre bots y un solo usuario.
  • groupChatChat entre un bot y dos o más usuarios.

Un bot se comporta de forma ligeramente diferente según el tipo de conversación en la que esté involucrado:

Para que el bot funcione en un ámbito determinado, debe figurar como compatible con ese ámbito en el manifiesto. Los ámbitos se definen y analizan más adelante 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
  • Mensajes de sondeo

Conceptos básicos de la conversación

Cada mensaje es un Activity objeto de tipo messageType: message. Cuando un usuario envía un mensaje, Teams publica el mensaje en el bot; específicamente, 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 responde en consecuencia.

Los bots también admiten mensajes de estilo de evento. Para obtener más información, consulte Controlar eventos de bot en Microsoft Teams. 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 en la interfaz de usuario y diferencias entre bastidores, que debe conocer.

La conversación básica se controla a través de Bot Framework Connector, una única API de REST para permitir que el bot se comunique con Teams y otros canales. El SDK de Bot Builder proporciona fácil acceso 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 del 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 su bot puede controlar en la página de configuración de Microsoft Teams para su bot.

Formato Del usuario al bot De bot a usuario Notas
Texto enriquecido
Imágenes Máximo de 1024×1024 MB 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 compatibles.
Emojis Teams admite emojis a través de UTF-16, como U+1F600 para cara sonriente.

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

Formato de mensaje

Puede establecer la propiedad opcional TextFormat de a 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 los equipos, consulte Formato de texto en los mensajes del bot.

Para obtener más información sobre cómo dar formato a las tarjetas en los mensajes, consulte 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 documentación de Bot Framework.

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

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

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

Recibir mensajes

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

  • Chat personal Los usuarios pueden interactuar en una conversación privada con un bot seleccionando el bot agregado en el historial de chats o escribiendo su nombre o id. de aplicación en el cuadro Para: de un nuevo chat.
  • Canales Se puede mencionar un bot ("@botname") 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á a las respuestas en las que no se mencione.

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

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

  • 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 se refiere a un canal de bot framework, no a un canal de equipos.
  • 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 significativa para identificar a ese usuario.
  • channelData.tenant.id Identificador del espacio empresarial del usuario.

Nota

from.id es única 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 privadas y de canal con el bot

Al interactuar en un canal, el bot debe ser inteligente a la hora de 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 que el canal vea toda la secuencia de interacciones, considere la posibilidad de enviar un mensaje de chat personal al usuario. El bot debe 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 de los mensajes entrantes a veces contiene menciones. Asegúrese de revisarlos y pelarlos adecuadamente. Para obtener más información, vea Menciones.

Datos del canal de Teams

El channelData objeto 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 estos identificadores 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; Solo se pasa en casos de eventos de modificación de canal.
  • tenant.idId. de inquilino de Microsoft Entra; pasado en todos los contextos.
  • team Se pasa solo 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 en equipos donde se ha agregado el bot.
  • channelData.teamsTeamId En desuso. Esta propiedad se incluye solo por motivos de compatibilidad con versiones anteriores.
  • channelData.teamsChannelId En desuso. Esta propiedad se incluye solo por motivos de 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 especializado TeamsChannelData que expone las propiedades para acceder a información específica de Teams.

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

Enviar respuestas a mensajes

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

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

El contenido del mensaje en sí puede contener texto simple o algunas de las tarjetas y acciones de tarjeta proporcionadas por Bot Framework.

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

Actualización de mensajes

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

No es necesario que el nuevo mensaje coincida con el original en 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 de mensajes con varios datos adjuntos en el diseño de lista.

REST API

Para emitir una actualización de mensajes, realice una solicitud PUT en el punto de /v3/conversations/<conversationId>/activities/<activityId>/ conexión con 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 UpdateActivityAsync método del 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);
  }
}

Node.js ejemplo

Puede usar el session.connector.update método del 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 mensajes a su usuario o usuarios sin que inicien primero el contacto con el bot. Para obtener más información, vea los siguientes artículos:

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

Eliminación de mensajes

Los mensajes se pueden eliminar utilizando 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);
  });
})