Enviar y recibir mensajes

Los agentes conversacionales se comunican con los usuarios a través de la mensajería, lo que permite interacciones fluidas. Puede simular conversaciones de la vida real con usuarios a través de interacciones de texto o voz. Debe asegurarse de que las conversaciones de los agentes sean interactivas, dinámicas, adaptables y fáciles de usar.

Contenido del mensaje

La interacción de mensajes entre su agente y el usuario puede incluir diferentes tipos de contenido de mensajes que:

Tipo de contenido Del usuario al agente Del agente al usuario
Texto enriquecido y emojis ✔️ ✔️
Imágenes ✔️ ✔️
Tarjetas adaptables ✔️

Usar mensajes de texto enriquecido y emojis

El agente de Teams puede enviar texto enriquecido y emojis. Teams admite emojis a través de UTF-16, como U+1F600 para una cara sonriente.

Usar mensajes de imagen

Para que los mensajes del agente destaquen, el usuario puede agregar imágenes como datos adjuntos:

  • Las imágenes pueden tener hasta 1024 × 1024 píxeles y 1 MB en formato PNG, JPEG o GIF. No se admiten los GIF animados.

  • Puede especificar la altura y el ancho de cada imagen mediante XML. En Markdown, el tamaño de imagen predeterminado es 256×256. Por ejemplo:

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

Para obtener más información sobre los datos adjuntos, vea Agregar datos adjuntos multimedia a los mensajes.

Nota:

En entornos GCC High y DoD, incruste imágenes en mensajes o tarjetas de bot como contenido codificado en base64 porque los vínculos de imagen externos no se pueden representar. Para obtener más información, consulte Límites y especificaciones de Microsoft Teams.

Usar tarjetas adaptables

Un agente conversacional puede incluir tarjetas adaptables que simplifican los flujos de trabajo empresariales. Las tarjetas adaptables ofrecen texto, voz, imágenes, botones y campos de entrada personalizables enriquecidos. Puedes crear tarjetas adaptables en un agente y mostrarlas en varias aplicaciones, como Teams, tu sitio web, etc.

Para más información, vea:

En el código siguiente se muestra un ejemplo de envío de una tarjeta adaptativa simple:

Ejemplo: enviar una tarjeta adaptativa sencilla
{
    "type": "AdaptiveCard",
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
    "version": "1.5",
    "body": [
    {
        "items": [
        {
            "size": "large",
            "text": "Simple Adaptive Card example with a Textbox",
            "type": "TextBlock",
            "weight": "bolder",
            "wrap": true
        },
        ],
        "spacing": "extraLarge",
        "type": "Container",
        "verticalContentAlignment": "center"
    }
    ]
}

Enviar y recibir mensajes

Enviar y recibir mensajes es la funcionalidad básica de un agente.

En un chat, cada mensaje es un Activity objeto de tipo messageType: message. Cuando alguien envía un mensaje, Microsoft Teams lo publica para su agente. Teams envía un objeto JSON al punto de conexión de mensajería del agente y solo permite un punto de conexión para la mensajería. A continuación, el agente comprueba el mensaje para averiguar su tipo y responde en consecuencia.

Las conversaciones básicas se administran a través del conector de Teams SDK Framework, que es una única API de REST. Esta API permite a su agente hablar con Teams y otros canales. El SDK de Bot Builder ofrece las siguientes características:

  • Fácil acceso al conector de SDK Framework de Teams.
  • Herramientas para administrar el flujo y el estado de la conversación.
  • Formas sencillas de agregar servicios cognitivos, como el procesamiento del lenguaje natural (NLP).

El agente recibe mensajes de Teams con la Text propiedad y puede devolver una o varias respuestas a los usuarios.

Para obtener más información, consulte atribución de usuario para los mensajes de agente.

La siguiente tabla enumera la actividad que el agente puede recibir y sobre la que puede tomar medidas:

Tipo de mensaje Objeto de carga Ámbito
Actividad Recibir un mensaje Actividad de mensajes todas
Recibir actividad de edición de mensajes Actividad de edición de mensajes todas
Recibir actividad de recuperar mensajes Actividad de recuperación de mensajes todas
Recibir actividad de mensajes de eliminación temporal Actividad de eliminación temporal de mensajes todas

Actividad Recibir un mensaje

Para recibir un mensaje de texto, use la Text propiedad de un Activity objeto. En el controlador de actividad del agente, use el objeto de contexto turn Activity para leer una sola solicitud de mensaje.

El código siguiente muestra un ejemplo de recepción de una actividad de mensajes:

app.OnMessage(async context =>
{
    await context.Send($"Echo: {context.Activity.Text}");
});

app.on('message', async ({ activity, send }) => {
    await send(`Echo: '${activity.text}'`);
});

@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]):
    await ctx.send(f"Echo: {ctx.activity.text}")

{
    "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 TestAgent"
    },
    "textFormat": "plain",
    "text": "Hello Teams TestAgent.Sending bold-italic rich text",
    "attachments": [
      {
            "contentType": "text/html",
            "content": "<div><div>Hello Teams TestAgent. Sending <strong>bold</strong>-<em>italic</em> rich text.</div>\n</div>"
      } 
    ],
    "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"
}

Recibir una confirmación de lectura

La configuración Confirmaciones de lectura en Teams permite que el remitente de un mensaje de chat sea notificado cuando el destinatario leyó el mensaje en chats individuales y grupales. Después de que el destinatario lea el mensaje, lo que verá aparecerá junto al mensaje. También tiene la opción de configurar su agente para recibir eventos de confirmación de lectura a través de la configuración Confirmaciones de lectura . El evento de confirmación de lectura le ayuda a mejorar la experiencia del usuario de las siguientes maneras:

  • Puede configurar su agente para que envíe un mensaje de seguimiento si el usuario de la aplicación no ha leído el mensaje en el chat personal.

  • Puedes crear un bucle de comentarios usando confirmaciones de lectura para ajustar la experiencia de tu agente.

Nota:

  • Las confirmaciones de lectura solo se admiten en escenarios de chat de usuario a agente.
  • Las confirmaciones de lectura de los agentes no admiten ámbitos de chat de equipo, canal y grupo.
  • Si un administrador o usuario deshabilita la configuración de confirmaciones de lectura , el agente no recibe el evento de confirmación de lectura.

Para recibir eventos de confirmación de lectura para el agente, asegúrese de lo siguiente:

  • Agregue el permiso RSCChatMessageReadReceipt.Read.Chat en el manifiesto de la aplicación, como se indica a continuación:

    
    "webApplicationInfo": {
    
         "id": "38f0ca43-1c38-4c39-8097e-47f62c686500",
         "resource": ""
    },
    "authorization": {
        "permissions": {
        "orgwide": [],
         "resourceSpecific": [
            {
            "name": "ChatMessageReadReceipt.Read.Chat",
            "type": "Application"
            }
            ]
         }
     }
    
    

También puede agregar permisos RSC mediante la API de Graph API. Para más información, vea consentedPermissionSet.

  • Invalidar el método OnReadReceipt con context.Activity.Value.LastReadMessageId.

    El context.Activity.Value.LastReadMessageIdmétodo es útil para determinar si los destinatarios leen el mensaje. Si es compareMessageId menor o igual que , LastReadMessageIdentonces el mensaje se ha leído. Invalidar el OnReadReceipt método para recibir confirmaciones de lectura con context.Activity.Value.LastReadMessageId el método:

    app.OnReadReceipt(async context =>
    
    {
        var lastReadMessageId = context.Activity.Value.LastReadMessageId;
        await context.Send("User read the agent's message");
    });
    

En el siguiente ejemplo se muestra una solicitud de evento de confirmaciones de lectura que recibe un agente:

    {
        "name": "application/vnd.microsoft.readReceipt",
        "type": "event",
        "timestamp": "2023-08-16T17:23:11.1366686Z",
        "id": "f:b4783e72-9d7b-2ed9-ccef-ab446c873007",
        "channelId": "msteams",
        "serviceUrl": "https://smba.trafficmanager.net/amer/",
        "from": {
            "id": "29:1-8Iuh70W9pRqV8tQK8o2nVjxz33RRGDKLf4Bh7gKnrzN8s7e4vCyrFwjkPbTCX_Co8c4aXwWvq3RBLr-WkkVMw",
            "aadObjectId": "5b649834-7412-4cce-9e69-176e95a394f5"
        },
        "conversation": {
            "conversationType": "personal",
            "tenantId": "6babcaad-604b-40ac-a9d7-9fd97c0b779f",
            "id": "a:1xlimp68NSUxEqK0ap2rXuwC9ITauHgV2M4RaDPkeRhV8qMaFn-RyilMZ62YiVdqs8pp43yQaRKvv_U2S2gOS5nM-y_pOxVe4BW1qMGPtqD0Bv3pw-nJXF0zhDlZHMZ1Z"
        },
        "recipient": {
            "id": "28:9901a8b6-4fef-428b-80b1-ddb59361adeb",
            "name": "Test Agent"
        },
        "channelData": {
            "tenant": {
                "id": "6babcaad-604b-40ac-a9d7-9fd97c0b779f"
            }
        },
        "value": {
            "lastReadMessageId": "1692206589131"
        }
    }
    
  • La configuración de administrador de confirmación de lectura o la configuración de usuario está activada para que el espacio empresarial para que el agente reciba los eventos de confirmación de lectura. El administrador o el usuario deben habilitar o deshabilitar la configuración de confirmación de lectura.

Después de habilitar el agente en un escenario de chat de usuario a agente, el agente recibe rápidamente un evento de confirmación de lectura cuando el usuario lee el mensaje del agente. Puede realizar un seguimiento de la participación del usuario contando el número de eventos y también puede enviar un mensaje contextual.

Recibir actividad de edición de mensajes

Al editar un mensaje, el agente recibe una notificación de la actividad de edición de mensajes.

Para obtener una notificación de actividad de edición de mensajes en un agente, puede invalidar OnMessageEdit el controlador.

A continuación se muestra un ejemplo de una notificación de actividad de edición de mensajes que utiliza OnMessageEdit cuando se edita un mensaje enviado:

app.OnMessageEdit(async context =>
{
    await context.Send("message is updated");
}); 
app.on('messageEdit', async ({ activity, send }) => {
    const editedMessage = activity.text;
    await send(`The edited message is ${editedMessage}`);
});
{
"type":"messageUpdate",
"timestamp":"2022-10-28T17:19:39.4615413Z",
"localTimestamp":"2022-10-28T10:19:39.4615413-07:00",
"id":"1666977568748",
"channelId":"msteams",
"serviceUrl":"https://canary.botapi.skype.com/amer/",
"from": {
    "id":"29:1BLjP9j3_PM4mubmQZsYPx7jDyLeLf_YVA9sVPV08KMAFMjJWB_EUGveb9EVDh9TslNp9qjnzEBy3kgw01Jf1Kg",
    "name":"Mike Wilber",
    "aadObjectId":"520e4d1e-2108-43ee-a092-46a9507c6200"caching
},
"conversation":{
    "conversationType":"personal",
    "tenantId":"528dbe3f-15e0-4e37-84a1-00cc305847dd","id":"a:1pweuGJ44RkB90tiJNQ_I6g3vyuP4CYA_f-v6f0Vd-Bs3Ce85C73Ah1y8TvyjESsTHWjjgw-gnsuIuCUOWkfOCq6qaUYsk2_-fj93XXXHUMAUzhFFvTnaCU7V4WiMqRPB"
},
"recipient":{
    "id":"28:0d569679-gb4j-479a-b0d8-238b6e6b1149",
    "name":"TestAgent"
},
"entities":[
    {
        "locale":"en-US",
        "country":"US",
        "platform":"Web",
        "timezone":"America/Los_Angeles",
        "type":"clientInfo"
    }
],
"channelData":{
    "eventType":"editMessage",
    "tenant":{"id":"528dbe3f-15e0-4e37-84a1-00cc305847dd"}
},
"locale":"en-US",
"localTimezone":"America/Los_Angeles"
}  
PUT {Service URL of your agent}/v3/conversations/{conversationId}/activities/{activityId}
{
    "type": "message",
    "text": "This message has been updated"
}

Enviar un mensaje

Para enviar un mensaje de texto, especifique la cadena que desea enviar como actividad. En el controlador de actividad del agente, use el método del objeto de context.Send(...) contexto turn para enviar una sola respuesta de mensaje. Use el método del multiple context.Send(...) calls objeto para enviar varias respuestas.

El código siguiente muestra un ejemplo de envío de un mensaje cuando se agrega un usuario a una conversación:

app.OnMembersAdded(async context =>
{
    foreach (var member in context.Activity.MembersAdded)
    {
        if (member.Id != context.Activity.Recipient.Id)
        {
            await context.Send("Hello and welcome!");
        }
    }
});
   app.on('membersAdded', async ({ activity, send }) => {
    for (const member of activity.membersAdded ?? []) {
        if (member.id !== activity.recipient.id) {
            await send(`Welcome to the team ${member.name}`);
        }
    }
});
@app.on_members_added
async def handle_members_added(ctx: ActivityContext):
    for member in ctx.activity.members_added:
        if member.id != ctx.activity.recipient.id:
            await ctx.send(f"Welcome your new team member {member.id}")
{
    "type": "message",
    "from": {
        "id": "28:c9e8c047-2a34-40a1-b28a-b162d5f5327c",
        "name": "Teams TestAgent"
    },
    "conversation": {
        "id": "a:17I0kl8EkpE1O9PH5TWrzrLNwnWWcfrU7QZjKR0WSfOpzbfcAg2IaydGElSo10tVr4C7Fc6GtieTJX663WuJCc1uA83n4CSrHSgGBj5XNYLcVlJAs2ZX8DbYBPck201w-",
        "name": "Convo1"
   },
   "recipient": {
        "id": "29:1XJKJMvc5GBtc2JwZq0oj8tHZmzrQgFmB25ATiQWA85gQtHieVkKilBZ9XHoq9j7Zaqt7CZ-NJWi7me2kHTL3Bw",
        "name": "Megan Bowen"
    },
    "text": "My agent's reply",
    "replyToId": "1632474074231"
}
HTTP Request: {Service URL of your agent}/v3/conversations/{conversationId}/activities
{
    "type": "message",
    "from": {
        "id": "28:c9e8c047-2a34-40a1-b28a-b162d5f5327c",
        "name": "Teams TestAgent"
    },
    "conversation": {
        "id":"a:17I0kl8EkpE1O9PH5TWrzrLNwnWWcfrU7QZjKR0WSfOpzbfcAg2IaydGElSo10tVr4C7Fc6GtieTJX663WuJCc1uA83n4CSrHSgGBj5XNYLcVlJAs2ZX8DbYBPck201w-",
        "name": "Convo1"
    },
    "recipient": {
        "id": "29:1XJKJMvc5GBtc2JwZq0oj8tHZmzrQgFmB25ATiQWA85gQtHieVkKilBZ9XHoq9j7Zaqt7CZ-NJWi7me2kHTL3Bw",
        "name": "Megan Bowen"
    },
    "text": "My agent's reply"
}

Nota:

  • La división de mensajes se produce cuando se envían un mensaje de texto y datos adjuntos en la misma carga de actividad. Teams divide esta actividad en dos actividades independientes, una con un mensaje de texto y la otra con datos adjuntos. Al dividir la actividad, no recibirá el id. del mensaje en respuesta, que se usa para actualizar o eliminar el mensaje de forma proactiva. Se recomienda enviar actividades separadas en lugar de depender de la división de mensajes.
  • Los mensajes enviados se pueden localizar para proporcionar personalización. Para obtener más información, consulte Localizar su aplicación.

Los mensajes enviados entre usuarios y agentes incluyen datos de canal internos dentro del mensaje. Estos datos permiten al agente comunicarse correctamente en ese canal. El SDK de Bot Builder le permite modificar la estructura del mensaje.

Recibir actividad de recuperar mensajes

Al recuperar un mensaje, el agente recibe una notificación de la actividad de recuperar mensajes.

Para obtener una notificación de actividad de mensajes de recuperación en un agente, puede anular OnMessageUndelete el controlador.

A continuación se muestra un ejemplo de una notificación de actividad de mensajes de recuperación que se utiliza OnMessageUndelete cuando se restaura un mensaje eliminado:

app.OnMessageUndelete(async context =>
{
    await context.Send("message is undeleted");
});
app.on('messageUndelete', async ({ activity, send }) => {
    const undeletedMessage = activity.text;
    await send(`Previously the message was deleted. After undeleting, the message is now: "${undeletedMessage}"`);
});
{
"type":"messageUpdate",
"timestamp":"2022-10-28T17:19:39.4615413Z",
"localTimestamp":"2022-10-28T10:19:39.4615413-07:00",
"id":"1666977568748",
"channelId":"msteams",
"serviceUrl":"https://canary.botapi.skype.com/amer/",
"from": {
    "id":"29:1BLjP9j3_TM4mubmQZsYEo7jDyLeLf_YVA9sVPVO7KMAFMjJWB_EUGveb9EVDh9LgoNp9qjnzEBy4kgw83Jf1Kg",
    "name":"Alex Wilber",
    "aadObjectId":"976e4d1e-2108-43ee-a092-46a9507c5606"
},
"conversation":{
    "conversationType":"personal",
    "tenantId":"528dbe3f-15e0-4e37-84a1-00cc305847dd","id":"a:1tewuGJ44RkB90tiJNQ_I4q8vyuN5CYA_f-v6f0Vd-Bs3Ce85C73Ah1y8TvyjESsTHWjjgw-gnsuIuCUOWkfOCq6qaUYsk2_-fj93XXXHUMAUzhFFvTnaCU7V4WiMqXQL"
},
"recipient":{
    "id":"28:0d469698-ab9d-479a-b0d8-758b6e6b1234",
    "name":"Testbot"
},
"entities":[
    {
           "locale":"en-US",
        "country":"US",
        "platform":"Web",
        "timezone":"America/Los_Angeles",
        "type":"clientInfo"
    }
],
"channelData":{
    "eventType":"undeleteMessage",
    "tenant":{"id":"528dbe3f-15e0-4e37-84a1-00cc305847dd"}
},
"locale":"en-US",
"localTimezone":"America/Los_Angeles"
}  
PUT {Service URL of your agent}/v3/conversations/{conversationId}/activities/{activityId}
{
    "type": "message",
    "text": "This message has been updated"
}

Recibir actividad de mensajes de eliminación temporal

Al eliminar un mensaje de forma temporal, el agente recibe una notificación de la actividad de mensajes de eliminación temporal.

Para obtener una notificación de actividad por mensaje de eliminación temporal en un agente, puede invalidar OnMessageSoftDelete el controlador.

En el ejemplo siguiente se muestra una notificación de actividad de mensaje de eliminación temporal cuando OnMessageSoftDelete se elimina un mensaje de forma temporal:

app.OnMessageSoftDelete(async context =>
{
    await context.Send("message is soft deleted");
}); 
app.on('messageSoftDelete', async ({ activity, send }) => {
    const messageId = activity.id;
    await send(`The deleted message id is ${messageId}`);
});

{
"type":"messageDelete",
"timestamp":"2022-10-28T17:19:43.1612052Z",
"localTimestamp":"2022-10-28T10:19:43.1612052-07:00",
"id":"1666977568748",
"channelId":"msteams",
"serviceUrl":"https://canary.botapi.skype.com/amer/",
"from": {
    "id":"29:1BLjP9j3_TM4mubmQZsYEo7jDyLeLf_YVA9sVPVO7KMAFMjJWB_EUGveb9EVDh9LgoNp9qjnzEBy4kgw83Jf1Kg",
    "name":"Alex Wilber",
    "aadObjectId":"976e4d1e-2108-43ee-a092-46a9507c5606"
},
"conversation":{
    "conversationType":"personal",
    "tenantId":"528dbe3f-15e0-4e37-84a1-00cc305847dd","id":"a:1tewuGJ44RkB90tiJNQ_I4q8vyuN5CYA_f-v6f0Vd-Bs3Ce85C73Ah1y8TvyjESsTHWjjgw-gnsuIuCUOWkfOCq6qaUYsk2_-fj93XXXHUMAUzhFFvTnaCU7V4WiMqXQL"
},
"recipient":{
    "id":"28:0d469698-ab9d-479a-b0d8-758b6e6b1235",
    "name":"Testagent"
},
"entities":[
    {
        "locale":"en-US",
        "country":"US",
        "platform":"Web",
        "timezone":"America/Los_Angeles",
        "type":"clientInfo"
    }
],
"channelData":{
    "eventType":"softDeleteMessage",
    "tenant":{"id":"528dbe3f-15e0-4e37-84a1-00cc305847dd"}
},
"locale":"en-US",
"localTimezone":"America/Los_Angeles"
}  

Actualizar y eliminar mensajes enviados desde el agente

Importante

Los ejemplos de código de esta sección se basan en la versión 4.6 y versiones posteriores del SDK de Bot Framework. Si busca documentación para versiones anteriores, consulte la sección bots - SDK v3 en la carpeta SDK heredados de la documentación.

El agente puede actualizar mensajes dinámicamente después de enviarlos en lugar de tenerlos como instantáneas estáticas de datos. Los mensajes también se pueden eliminar mediante el método del marco del SDK de context.Api.Conversations.Activities.DeleteAsync(...) Teams.

Nota:

Un agente no puede actualizar ni eliminar mensajes enviados por el usuario en Microsoft Teams.

Actualizar mensajes

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.

No es necesario que el nuevo mensaje coincida con el tipo original. Por ejemplo, si el mensaje original contenía datos adjuntos, el nuevo mensaje puede ser un mensaje de texto simple.

Referencia de código de ejemplo

Para actualizar un mensaje existente, pase un nuevo Activity objeto con el identificador de actividad existente al contexto. Api.Conversations.Activities.UpdateAsync(...)method of theTurnContext'.

app.OnMessage(async context =>
{
    // Send initial message
    var response = await context.Send("Your Message");
    var conversationId = context.Activity.Conversation.Id;
    var activityId = response.Id;

    var updatedActivity = new MessageActivity("The new text for the activity");

    await context.Api.Conversations.Activities.UpdateAsync(conversationId, activityId, updatedActivity);
});

Para actualizar un mensaje existente, pase un nuevo objeto Activity con el identificador de actividad existente al método updateActivity del objeto TurnContext.

app.on('message', async ({ activity, api, send }) => {
    // Send initial message
    const response = await send('Your Message');
    const conversationId = activity.conversation.id;
    const activityId = response.id;

    await api.conversations.activities(conversationId).update(activityId, {
        type: 'message',
        text: 'The new text for the activity'
    });
});

Para actualizar un mensaje existente, pase un nuevo objeto Activity con el identificador de actividad existente al método context.Api.Conversations.Activities.UpdateAsync(...) de la clase TurnContext.

@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]):
    # Send initial message
    response = await ctx.send("Your Message")
    conversation_id = ctx.activity.conversation.id
    activity_id = response.id

    await ctx.api.conversations.activities(conversation_id).update(
        activity_id, MessageActivityInput(text="The new text for the activity")
    )

Nota:

Puede desarrollar aplicaciones de Teams en cualquier tecnología de programación web y llamar directamente a las API de REST del servicio Bot Connector. Para ello, debe implementar la Autenticación de procedimientos seguridad con sus solicitudes de API.

Para actualizar una actividad existente en una conversación, incluya el conversationId y activityId en el punto de conexión de solicitud. Para completar este escenario, debe almacenar en caché el identificador de actividad devuelto por la llamada post original.

PUT /v3/conversations/{conversationId}/activities/{activityId}
Solicitud Respuesta
Un objeto de Actividad. Un objeto ResourceResponse.

Ahora que ha actualizado los mensajes, actualice la tarjeta existente en la selección de botón para las actividades entrantes.

Actualizar tarjetas

Para actualizar la tarjeta existente en la selección de botón, puede usar ReplyToId de actividad entrante.

Referencia de código de ejemplo

Para actualizar la tarjeta existente en una selección de botón, pase un nuevo objeto Activity con tarjeta actualizada y ReplyToId como identificador de actividad al método context.Api.Conversations.Activities.UpdateAsync(...) de la clase TurnContext.

app.OnMessage(async context =>
{
    var conversationId = context.Activity.Conversation.Id;
    var activityId = context.Activity.ReplyToId;

    var updatedActivity = new MessageActivity();
    updatedActivity.Attachments.Add(card.ToAttachment());

    await context.Api.Conversations.Activities.UpdateAsync(conversationId, activityId, updatedActivity);
});

Para actualizar la tarjeta existente en una selección de botón, pase un nuevo objeto Activity con tarjeta actualizada y replyToId como identificador de actividad al método updateActivity del objeto TurnContext.

app.on('message', async ({ activity, api }) => {
    const conversationId = activity.conversation.id;
    const activityId = activity.replyToId;

    await api.conversations.activities(conversationId).update(activityId, {
        type: 'message',
        attachments: [card]
    });
});

Para actualizar la tarjeta existente al hacer clic en un botón, pase un nuevo objeto Activity con tarjeta actualizada y reply_to_id como identificador de actividad al método ctx.api.conversations.activities(conversation_id).update(...) de la clase TurnContext.

@app.on_message
async def handle_update_card(ctx: ActivityContext[MessageActivity]):
    conversation_id = ctx.activity.conversation.id
    activity_id = ctx.activity.reply_to_id

    await ctx.api.conversations.activities(conversation_id).update(
        activity_id, MessageActivityInput().add_card(card)
    )

Nota:

Puede desarrollar aplicaciones de Teams en cualquier tecnología de programación web y llamar directamente a las API de REST del servicio Bot Connector. Para ello, debe implementar la autenticación de procedimientos de seguridad con las solicitudes de API.

Para actualizar una actividad existente en una conversación, incluya el conversationId y activityId en el punto de conexión de solicitud. Para completar este escenario, debe almacenar en caché el identificador de actividad devuelto por la llamada post original.

PUT /v3/conversations/{conversationId}/activities/{activityId}
Solicitud Respuesta
Un objeto de actividad. Un objeto ResourceResponse.

Ahora que ha actualizado las tarjetas, puede eliminar mensajes con el marco del SDK de Teams.

Eliminar mensajes

En el SDK Framework de Teams, cada mensaje tiene su identificador de actividad único. Los mensajes se pueden eliminar mediante el método del marco del SDK de context.Api.Conversations.Activities.DeleteAsync(...) Teams.

Referencia de código de ejemplo

Para eliminar un mensaje, pase el identificador de esa actividad al método context.Api.Conversations.Activities.DeleteAsync(...) de la clase TurnContext.

app.OnMessage(async context =>
{
    var conversationId = context.Activity.Conversation.Id;

    foreach (var activityId in _list)
    {
        await context.Api.Conversations.Activities.DeleteAsync(conversationId, activityId);
    }
});

Referencia de código de ejemplo

Para eliminar un mensaje, pase el identificador de esa actividad al método context.Api.Conversations.Activities.DeleteAsync(...) del objeto TurnContext.

app.on('message', async ({ activity, api }) => {
    const conversationId = activity.conversation.id;

    for (const activityId of activityIds) {
        await api.conversations.activities(conversationId).delete(activityId);
    }
});

Para eliminar ese mensaje, pase el identificador de esa actividad al método delete_activity del objeto TurnContext.

@app.on_message
async def handle_delete(ctx: ActivityContext[MessageActivity]):
    conversation_id = ctx.activity.conversation.id

    for activity_id in _list:
        await ctx.api.conversations.activities(conversation_id).delete(activity_id)

Para eliminar una actividad existente en una conversación, incluya el conversationId y activityId en el punto de conexión de la solicitud.

DELETE /v3/conversations/{conversationId}/activities/{activityId}
Solicitud y respuesta Descripción
N/D Código de estado HTTP que indica el resultado de la operación. No se especifica nada en el cuerpo de la respuesta.

Respuestas citadas

Las respuestas entre comillas permiten a su agente hacer referencia a un mensaje anterior en la conversación. Cuando un usuario envía un mensaje que cita otro mensaje, su agente recibe metadatos estructurados sobre el contenido citado. Su agente también puede enviar mensajes que citan mensajes anteriores.

Recibir respuestas citadas

Cuando un usuario cita un mensaje y lo envía a su agente, los metadatos de la respuesta citada están disponibles en la actividad entrante. Utilice el GetQuotedMessages método para tener acceso a todas las entidades de respuesta citadas.

app.OnMessage(async context =>
{
    var quotes = context.Activity.GetQuotedMessages();

    if (quotes.Count > 0)
    {
        var quote = quotes[0].QuotedReply;
        await context.Reply(
            $"You quoted message {quote.MessageId} from {quote.SenderName}: \"{quote.Preview}\"");
    }
});

Cuando un usuario cita un mensaje y lo envía a su agente, los metadatos de la respuesta citada están disponibles en la actividad entrante. Utilice el getQuotedMessages método para tener acceso a todas las entidades de respuesta citadas.

app.on('message', async ({ activity, reply }) => {
  const quotes = activity.getQuotedMessages();

  if (quotes.length > 0) {
    const quote = quotes[0].quotedReply;
    await reply(
      `You quoted message ${quote.messageId} from ${quote.senderName}: "${quote.preview}"`
    );
  }
});

Cuando un usuario cita un mensaje y lo envía a su agente, los metadatos de la respuesta citada están disponibles en la actividad entrante. Utilice el get_quoted_messages método para tener acceso a todas las entidades de respuesta citadas.

@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]):
    quotes = ctx.activity.get_quoted_messages()

    if quotes:
        quote = quotes[0].quoted_reply
        await ctx.reply(
            f"You quoted message {quote.message_id} from {quote.sender_name}: \"{quote.preview}\""
        )

Enviar respuestas entrecomilladas

Cuando el agente llama, Reply()el SDK marca automáticamente una entidad de respuesta entrecomillada que hace referencia al mensaje entrante. La respuesta aparecerá como una respuesta entrecomillada en Teams.

app.OnMessage(async context =>
{
    // Reply() automatically quotes the inbound message
    await context.Reply("Got it!");
});

Para citar un mensaje diferente en la misma conversación (no en el mensaje entrante), use el Quote() método con el identificador de mensaje que desea citar.

app.OnMessage(async context =>
{
    // Quote a specific message by its ID
    var parentMessageId = "1772050244572";
    await context.Quote(parentMessageId, "Referencing an earlier message");
});

Cuando el agente llama, reply()el SDK marca automáticamente una entidad de respuesta entrecomillada que hace referencia al mensaje entrante. La respuesta aparecerá como una respuesta entrecomillada en Teams.

app.on('message', async ({ reply }) => {
  // reply() automatically quotes the inbound message
  await reply('Got it!');
});

Para citar un mensaje diferente en la misma conversación (no en el mensaje entrante), use el quote() método con el identificador de mensaje que desea citar.

app.on('message', async ({ quote }) => {
  // Quote a specific message by its ID
  const parentMessageId = '1772050244572';
  await quote(parentMessageId, 'Referencing an earlier message');
});

Cuando el agente llama, reply()el SDK marca automáticamente una entidad de respuesta entrecomillada que hace referencia al mensaje entrante. La respuesta aparecerá como una respuesta entrecomillada en Teams.

@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]):
    # reply() automatically quotes the inbound message
    await ctx.reply("Got it!")

Para citar un mensaje diferente en la misma conversación (no en el mensaje entrante), use el quote() método con el identificador de mensaje que desea citar.

@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]):
    # Quote a specific message by its ID
    parent_message_id = "1772050244572"
    await ctx.quote(parent_message_id, "Referencing an earlier message")

Cree respuestas entrecomilladas para enviar mensajes de forma proactiva

Para escenarios proactivos (usando app.Send()) o al citar varios mensajes, use el método en una actividad de AddQuote() mensaje. Pase el id. de mensaje y un texto de respuesta opcional.

var parentMessageId = "1772050244572";
var firstMessageId = "1772050244573";
var secondMessageId = "1772050244574";

// Single quote with response below it
var msg = new MessageActivity()
    .AddQuote(parentMessageId, "Here is my response");
await app.Send(conversationId, msg);

// Multiple quotes with interleaved responses
msg = new MessageActivity()
    .AddQuote(firstMessageId, "response to first")
    .AddQuote(secondMessageId, "response to second");
await app.Send(conversationId, msg);

// Grouped quotes — omit response to group quotes together
msg = new MessageActivity("see below for previous messages")
    .AddQuote(firstMessageId)
    .AddQuote(secondMessageId, "response to both");
await app.Send(conversationId, msg);

Para escenarios proactivos (usando app.send()) o al citar varios mensajes, use el método en una actividad de addQuote() mensaje. Pase el id. de mensaje y un texto de respuesta opcional.

import { MessageActivity } from '@microsoft/teams.api';

const parentMessageId = '1772050244572';
const firstMessageId = '1772050244573';
const secondMessageId = '1772050244574';

// Single quote with response below it
let msg = new MessageActivity()
  .addQuote(parentMessageId, 'Here is my response');
await app.send(conversationId, msg);

// Multiple quotes with interleaved responses
msg = new MessageActivity()
  .addQuote(firstMessageId, 'response to first')
  .addQuote(secondMessageId, 'response to second');
await app.send(conversationId, msg);

// Grouped quotes — omit response to group quotes together
msg = new MessageActivity('see below for previous messages')
  .addQuote(firstMessageId)
  .addQuote(secondMessageId, 'response to both');
await app.send(conversationId, msg);

Para escenarios proactivos (usando app.send()) o al citar varios mensajes, use el método en una actividad de add_quote() mensaje. Pase el id. de mensaje y un texto de respuesta opcional.

from microsoft_teams.api.activities.message import MessageActivityInput

parent_message_id = "1772050244572"
first_message_id = "1772050244573"
second_message_id = "1772050244574"

# Single quote with response below it
msg = (MessageActivityInput()
    .add_quote(parent_message_id, "Here is my response"))
await app.send(conversation_id, msg)

# Multiple quotes with interleaved responses
msg = (MessageActivityInput()
    .add_quote(first_message_id, "response to first")
    .add_quote(second_message_id, "response to second"))
await app.send(conversation_id, msg)

# Grouped quotes — omit response to group quotes together
msg = (MessageActivityInput(text="see below for previous messages")
    .add_quote(first_message_id)
    .add_quote(second_message_id, "response to both"))
await app.send(conversation_id, msg)

Enviar mensajes en los datos del canal de Teams

El channelData objeto contiene información específica de Teams y es una fuente definitiva de identificadores de equipo y canal. Opcionalmente, puede almacenar en caché y usar estos identificadores como claves para el almacenamiento local. En App el SDK se extrae información importante del channelData objeto para hacerlo accesible. Sin embargo, siempre podrá obtener acceso a los datos originales del turnContext objeto.

El channelData objeto no se incluye en los mensajes de las conversaciones personales, ya que tienen lugar fuera de un canal.

Un objeto típico channelData de una actividad enviada a su agente contiene la siguiente información:

  • eventType: El tipo de evento de Teams solo se pasa en casos de eventos de conversación en el agente de Teams.
  • tenant.id: Id. de inquilino de Microsoft Entra pasado en todos los contextos.
  • team: Se pasa solo en contextos de canal, no en chat personal.
  • channel: Se pasa solo en contextos de canal, cuando se menciona al agente o para eventos en canales en equipos, donde se agrega el agente.
  • channelData.teamsTeamId: Obsoleto. Esta propiedad solo se incluye por motivos de compatibilidad con versiones anteriores.
  • channelData.teamsChannelId: Obsoleto. Esta propiedad solo se incluye por motivos de compatibilidad con versiones anteriores.

El código siguiente muestra un ejemplo del 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"
    }
}

Datos del canal de Teams

El channelData objeto contiene información específica de Teams y es una fuente definitiva de identificadores de equipo y canal. Opcionalmente, puede almacenar en caché y usar estos identificadores como claves para el almacenamiento local. En App el SDK se extrae información importante del channelData objeto para hacerlo accesible. Sin embargo, siempre podrá obtener acceso a los datos originales del turnContext objeto.

El channelData objeto no se incluye en los mensajes de las conversaciones personales, ya que tienen lugar fuera de un canal.

Un objeto típico channelData de una actividad enviada a su agente contiene la siguiente información:

  • eventType: El tipo de evento de Teams solo se pasa en casos de eventos de modificación de canal.
  • tenant.id: Id. de inquilino de Microsoft Entra pasado en todos los contextos.
  • team: Se pasa solo en contextos de canal, no en chat personal.
    • id: GUID del canal.
    • name: nombre del equipo pasado solo en casos de (how-to/conversations/subscribe-to-conversation-events.md#team-renamed).
  • channel: Se pasa solo en contextos de canal, cuando se menciona al agente o para eventos en canales en equipos, donde se agrega el agente.
  • channelData.teamsTeamId: Obsoleto. Esta propiedad solo se incluye por motivos de compatibilidad con versiones anteriores.
  • channelData.teamsChannelId: Obsoleto. Esta propiedad solo se incluye por motivos de compatibilidad con versiones anteriores.

Ejemplo de objeto channelData

El código siguiente muestra un ejemplo del 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"
    }
}

Códigos de estado de las API conversacionales de agente

Asegúrese de controlar estos errores correctamente en la aplicación de Teams. En la tabla siguiente se enumeran los códigos de error y las descripciones en las que se generan los errores:

Código de estado Código de error y valores de mensaje Description Solicitud de reintento Acción del desarrollador
400 Código: Bad Argument
Mensaje: *específico del escenario
Carga de solicitud no válida proporcionada por el agente. Consulte el mensaje de error para obtener detalles específicos. No Vuelva a evaluar la carga útil de la solicitud para ver si hay errores. Compruebe el mensaje de error devuelto para obtener más información.
401 Código: BotNotRegistered
Mensaje: No se encontró ningún registro para este agente.
No se encontró el registro de este agente. No Compruebe el ID y la contraseña del agente. Asegúrese de que el bot ID (Microsoft Entra ID) esté registrado en el Portal para desarrolladores de Teams o a través del registro del canal de bot de Azure en Azure con el canal "Teams" habilitado.
403 Código: BotDisabledByAdmin
Mensaje: El administrador de inquilinos deshabilitó este agente
El Administrador bloqueó las interacciones entre el usuario y la aplicación del agente. El Administrador debe permitir la aplicación para el usuario dentro de las directivas de aplicación. Para obtener más información, consulte directivas de aplicaciones. No Detener la publicación en la conversación hasta que la interacción con el agente sea iniciada explícitamente por un usuario en la conversación, lo que indica que el agente ya no está bloqueado.
403 Código: BotNotInConversationRoster
Mensaje: El agente no forma parte de la lista de conversaciones.
El agente no forma parte de la conversación. La aplicación debe reinstalarse en la conversación. No Antes de intentar enviar otra solicitud de conversación, espere un installationUpdate evento, lo que indica que el agente se agrega de nuevo.
403 Código: ConversationBlockedByUser
Mensaje: El usuario bloqueó la conversación con el agente.
El usuario bloqueó al agente en un chat personal o en un canal a través de la configuración de moderación. No Elimine la conversación de la memoria caché. Deje de intentar publicar en conversaciones hasta que un usuario de la conversación inicie explícitamente la interacción con el agente, lo que indica que el agente ya no está bloqueado.
403 Código: ForbiddenOperationException
Mensaje: El agente no está instalado en el ámbito personal del usuario
El mensaje proactivo lo envía un agente, que no está instalado en un ámbito personal. No Antes de intentar enviar otra solicitud de conversación, instale la aplicación en el ámbito personal.
403 Código: InvalidBotApiHost
Mensaje: Host de API de agente no válido. Para inquilinos de GCC, llame a https://smba.infra.gcc.teams.microsoft.com.
El agente llamó al punto de conexión de API público para una conversación que pertenece a un inquilino de GCC. No Actualice la dirección URL del servicio para la conversación y vuelva a https://smba.infra.gcc.teams.microsoft.com intentar la solicitud.
403 Código: NotEnoughPermissions
Mensaje: *específico del escenario
El agente no tiene los permisos necesarios para realizar la acción solicitada. No Determine la acción requerida en el mensaje de error.
404 Código: ActivityNotFoundInConversation
Mensaje: Conversación no encontrada.
El id. de mensaje proporcionado no se encontró en la conversación. El mensaje no existe o se ha eliminado. No Compruebe si el Id. de mensaje enviado es un valor esperado. Quite el identificador si se almacenó en caché.
404 Código: ConversationNotFound
Mensaje: Conversación no encontrada.
No se encontró la conversación, ya que no existe o se ha eliminado. No Compruebe si el identificador de conversación enviado es un valor esperado. Quite el identificador si se almacenó en caché.
412 Código: PreconditionFailed
Mensaje: Error en la condición previa. Inténtelo de nuevo.
Se ha producido un error en una condición previa en una de nuestras dependencias debido a varias operaciones simultáneas en la misma conversación. Reintente con retroceso exponencial.
413 Código: MessageSizeTooBig
Mensaje: tamaño del mensaje demasiado grande.
El tamaño de la solicitud entrante era demasiado grande. Para obtener más información, consulte Dar formato a los mensajes del agente. No Reduzca el tamaño de la carga útil.
429 Código: Throttled
Mensaje: demasiadas solicitudes. También devuelve cuándo volver a intentarlo después.
Demasiadas solicitudes enviadas por el agente. Para obtener más información, consulte límite de frecuencia. Vuelva a intentar usar Retry-After el encabezado para determinar el tiempo de retroceso.
500 Código: ServiceError
Mensaje: *varios
Error interno del servidor. No Notifique el problema en la comunidad de desarrolladores.
Foros de la comunidad de desarrolladores.
502 Código: ServiceError
Mensaje: *varios
Problema de dependencia del servicio. Reintente con retroceso exponencial. Si el problema persiste, notifícalo en los foros de la comunidad de desarrolladores.
503 El servicio no está disponible. Reintente con retroceso exponencial. Si el problema persiste, notifícalo en la comunidad de desarrolladores.
504 Tiempo de espera agotado de la puerta de enlace. Reintente con retroceso exponencial. Si el problema persiste, notifícalo en la comunidad de desarrolladores.

Guía de reintento de códigos de estado

En la tabla siguiente se muestran instrucciones generales de reintento para cada código de estado. El agente debe evitar reintentar códigos de estado que no se especifiquen:

Código de estado Estrategia de reintento
403 Vuelva a intentarlo llamando a la API https://smba.infra.gcc.teams.microsoft.com GCC para InvalidBotApiHost.
412 Vuelva a intentarlo con el retroceso exponencial.
429 Vuelva a intentar utilizar Retry-After el encabezado para determinar el tiempo de espera en segundos y entre solicitudes, si está disponible. En caso contrario, vuelva a intentar usar el retroceso exponencial con el Id. de subproceso, si es posible.
502 Vuelva a intentarlo con el retroceso exponencial.
503 Vuelva a intentarlo con el retroceso exponencial.
504 Vuelva a intentarlo con el retroceso exponencial.

Solicitar encabezados del agente

Las solicitudes salientes actuales al agente no contienen en el encabezado ni en la URL ninguna información que ayude a los agentes a enrutar el tráfico sin desempaquetar toda la carga útil. Las actividades se envían al agente a través de una dirección URL similar a https://< your_domain>/api/messages. Se reciben solicitudes para mostrar el identificador de conversación y el identificador de inquilino en los encabezados.

Campos de encabezado de solicitud

Se agregan dos campos de encabezado de solicitud no estándar a todas las solicitudes enviadas a los agentes, tanto para el flujo asincrónico como para el flujo sincrónico. En la tabla siguiente se proporcionan los campos de encabezado de solicitud y sus valores:

Clave de campo Valor
x-ms-conversation-id Identificador de conversación correspondiente a la actividad de solicitud, si procede, y confirmado o verificado.
x-ms-tenant-id Identificador de inquilino correspondiente a la conversación en la actividad de solicitud.

Si el inquilino o el id. de conversación no está presente en la actividad o no se validó en el lado del servicio, el valor está vacío.

La imagen muestra los campos del encabezado.

Recibir solo los mensajes mencionados

Para permitir que los agentes obtengan solo los mensajes del canal o chat en los que está @mentionedsu agente, debe filtrar los mensajes. Use el siguiente fragmento de código para permitir que el agente reciba solo los mensajes en los que:@mentioned

  app.OnMessage(async context =>
{
    if (!context.Activity.GetMentions().Any(mention => mention.Mentioned.Id.Equals(context.Activity.Recipient.Id, StringComparison.OrdinalIgnoreCase)))
    {
        return;
    }

    await context.Send("Using RSC the agent can receive messages across channels or chats in team without being @mentioned.");
});

Si desea que el agente reciba todos los mensajes, no es necesario que los filtre @mention .

Paso siguiente

Conversaciones de chat grupal y de canal con un agente

Vea también

Eventos de conversación en el agente de Teams