Envoyer et recevoir des messages

Les agents conversationnels communiquent avec les utilisateurs par le biais de la messagerie, ce qui permet des interactions fluides. Il peut simuler des conversations réelles avec des utilisateurs par le biais d’interactions textuelles ou vocales. Vous devez vous assurer que les conversations des agents sont interactives, dynamiques, adaptatives et conviviales.

Contenu du message

L’interaction de messages entre votre agent et votre utilisateur peut inclure différents types de contenu de message qui :

Type de contenu D’utilisateur à agent De l’agent à l’utilisateur
Texte enrichi et emojis ✔️ ✔️
Images ✔️ ✔️
Cartes adaptatives ✔️

Utiliser le texte enrichi et les emojis

Votre agent Teams peut envoyer du texte enrichi et des emojis. Teams prend en charge les emojis via UTF-16, comme U+1F600 pour un visage souriant.

Utiliser des messages image

Pour que les messages des agents s’affichent, l’utilisateur peut ajouter des images en tant que pièces jointes :

  • Les images peuvent avoir une taille maximale de 1 024 × 1 024 pixels et 1 Mo au format PNG, JPEG ou GIF. Les GIF animés ne sont pas pris en charge.

  • Vous pouvez spécifier la hauteur et la largeur de chaque image à l’aide du format XML. Dans Markdown, la taille de l’image est par défaut de 256×256. Par exemple :

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

Pour plus d’informations sur les pièces jointes, voir Ajouter des pièces jointes multimédias à des messages.

Remarque

Dans les environnements GCC High et DoD, incorporez des images dans des messages ou des cartes de bot en tant que contenu codé en base64, car les liens d’image externes ne peuvent pas être rendus. Pour plus d’informations, consultez Limites et spécifications de Microsoft Teams.

Utiliser les cartes adaptatives

Un agent conversationnel peut inclure des cartes adaptatives qui simplifient les flux de travail professionnels. Les cartes adaptatives offrent un texte, des voix, des images, des boutons et des champs d’entrée riches et personnalisables. Vous pouvez créer des cartes adaptatives dans un agent et les afficher dans plusieurs applications telles que Teams, votre site web, etc.

Pour plus d’informations, reportez-vous aux rubriques suivantes :

Le code suivant montre un exemple d’envoi d’une carte adaptative simple :

Exemple : Envoyer une carte adaptative simple
{
    "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"
    }
    ]
}

Envoyer et recevoir des messages

L’envoi et la réception de messages constituent la fonctionnalité principale d’un agent.

Dans un chat, chaque message est un Activity objet de type messageType: message. Lorsque quelqu’un envoie un message, Microsoft Teams le publie vers votre agent. Teams envoie un objet JSON au point de terminaison de messagerie de votre agent, et il n’autorise qu’un seul point de terminaison pour la messagerie. Votre agent vérifie ensuite le type du message et répond en conséquence.

Les conversations de base sont gérées via le connecteur Teams SDK Framework, qui est une API REST unique. Cette API permet à votre agent de parler à Teams et à d’autres canaux. Le SDK Bot Builder offre les fonctionnalités suivantes :

  • Accès facile au connecteur de l’infrastructure du kit de développement logiciel (SDK) Teams.
  • Outils pour gérer le flux et l’état des conversations.
  • Méthodes simples pour ajouter des services cognitifs, comme le traitement du langage naturel (NLP).

Votre agent reçoit les messages des équipes utilisant la Text propriété et peut envoyer une ou plusieurs réponses aux utilisateurs.

Pour plus d’informations, voir Attribution utilisateur pour les messages d’agent.

Le tableau suivant répertorie l’activité que votre agent peut recevoir et sur laquelle vous pouvez agir :

Type de message Objet de charge utile Portée
Activité Recevoir un message Activité des messages tous
Activité de réception et de modification des messages Activité de modification de message tous
Activité de réception et de suppression de message Activité de restauration de message tous
Activité de réception de message de suppression réversible Activité de suppression réversible de message tous

Activité Recevoir un message

Pour recevoir un SMS, utilisez la Text propriété d’un Activity objet. Dans le gestionnaire d’activité de l’agent, utilisez les objets Activity de contexte turn pour lire une seule demande de message.

Le code suivant montre un exemple d’activité de réception d’un message :

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"
}

Recevoir une confirmation de lecture

Le paramètre Confirmations de lecture dans Teams permet à l’expéditeur d’un message de conversation d’être averti lorsque son message a été lu par le destinataire dans des conversations en individuelles et de groupe. Une fois que le destinataire a lu le message, la mention Vu apparaît à côté du message. Vous avez également la possibilité de configurer votre agent pour qu’il reçoive des événements de confirmation de lecture via le paramètre Confirmations de lecture . L’événement de confirmation de lecture vous permet d’améliorer l’expérience utilisateur des manières suivantes :

  • Vous pouvez configurer votre agent pour envoyer un message de suivi si l’utilisateur de votre application n’a pas lu le message dans la conversation personnelle.

  • Vous pouvez créer une boucle de commentaires à l’aide d’accusés de lecture pour optimiser l’expérience de votre agent.

Remarque

  • Les confirmations de lecture sont prises en charge uniquement dans les scénarios de conversation utilisateur-agent.
  • Les confirmations de lecture pour les agents ne prennent pas en charge les étendues des conversations d’équipe, de canal et de groupe.
  • Si un administrateur ou un utilisateur désactive le paramètre Confirmations de lecture , l’agent ne reçoit pas l’événement de confirmation de lecture.

Pour recevoir des événements d’accusé de lecture pour votre agent, vérifiez les points suivants :


Vous pouvez également ajouter des autorisations RSC via l’API Graph. Pour plus d’informations, reportez-vous à l’article consentedPermissionSet.

  • Remplacez la méthode OnReadReceipt par context.Activity.Value.LastReadMessageId.

    Cette context.Activity.Value.LastReadMessageIdméthode est utile pour déterminer si le message est lu par les destinataires. Si la compareMessageId est inférieure ou égale à , LastReadMessageIdalors le message a été lu. Remplacez la méthode pour recevoir les confirmations de lecture par context.Activity.Value.LastReadMessageId la OnReadReceipt méthode :

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

L’exemple suivant montre une demande d’événement de confirmations de lecture qu’un agent reçoit :

    {
        "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"
        }
    }
    
  • Le paramètre d’administration de la confirmation de lecture ou le paramètre utilisateur est activé pour le locataire afin que l’agent puisse recevoir les événements de confirmation de lecture. L’administrateur ou l’utilisateur doit activer ou désactiver le paramètre de confirmation de lecture.

Une fois l’agent activé dans un scénario de conversation utilisateur-agent, l’agent reçoit rapidement un événement de confirmation de lecture lorsque l’utilisateur lit le message de l’agent. Vous pouvez suivre l’engagement des utilisateurs en comptant le nombre d’événements et vous pouvez également envoyer un message contextuel.

Activité de réception et de modification des messages

Lorsque vous modifiez un message, l’agent reçoit une notification de l’activité de modification du message.

Pour obtenir une notification d’activité de modification de message dans un agent, vous pouvez remplacer OnMessageEdit le gestionnaire.

Voici un exemple de notification d’activité de modification de message utilisant OnMessageEdit la modification d’un message envoyé :

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"
}

Envoyer un message

Pour envoyer un SMS, spécifiez la chaîne que vous souhaitez envoyer en tant qu’activité. Dans le gestionnaire d’activité de l’agent, utilisez la méthode de l’objet context.Send(...) de contexte turn pour envoyer une réponse au message unique. Utilisez la méthode de l’objet multiple context.Send(...) calls pour envoyer plusieurs réponses.

Le code suivant montre un exemple d’envoi d’un message lorsqu’un utilisateur est ajouté à une conversation :

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"
}

Remarque

  • Le fractionnement de message se produit lorsqu’un SMS et une pièce jointe sont envoyés dans la même charge utile d’activité. Teams divise cette activité en deux activités distinctes, l’une avec un SMS et l’autre avec une pièce jointe. Lorsque l’activité est fractionnée, vous ne recevez pas l’ID de message en réponse, qui est utilisé pour mettre à jour ou supprimer le message de manière proactive. Il est recommandé d’envoyer des activités distinctes au lieu de dépendre du fractionnement des messages.
  • Les messages envoyés peuvent être localisés pour offrir une plus grande personnalisation. Pour plus d’informations, consultez Localiser votre application.

Les messages échangés entre les utilisateurs et les agents incluent des données de canal interne dans le message. Ces données permettent à l’agent de communiquer correctement sur ce canal. Le SDK Bot Builder vous permet de modifier la structure des messages.

Activité de réception et de suppression de message

Lorsque vous annulez la suppression d’un message, l’agent reçoit une notification de l’activité d’annulation de la suppression du message.

Pour obtenir une notification d’activité de message annulée dans un agent, vous pouvez remplacer OnMessageUndelete le gestionnaire.

Voici un exemple de notification d’activité de message d’annulation de la suppression utilisant OnMessageUndelete la restauration d’un message supprimé :

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"
}

Activité de réception de message de suppression réversible

Lorsque vous supprimez un message de manière réversible, l’agent reçoit une notification pour l’activité de suppression réversible du message.

Pour obtenir une notification d’activité de message de suppression réversible dans un agent, vous pouvez remplacer OnMessageSoftDelete le gestionnaire.

L’exemple suivant illustre une notification d’activité de message de suppression réversible utilisée OnMessageSoftDelete lorsqu’un message est supprimé de manière réversible :

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"
}  

Mettre à jour et supprimer les messages envoyés à partir de l’agent

Importante

Les échantillons de code de cette section sont basés sur la version 4.6 et les versions ultérieures du SDK Bot Framework. Si vous recherchez de la documentation pour les versions antérieures, consultez la section bots - SDK v3 dans le dossier SDK hérités de la documentation.

Votre agent peut mettre à jour dynamiquement les messages après les avoir envoyés au lieu de les avoir sous forme d’instantanés statiques de données. Les messages peuvent également être supprimés context.Api.Conversations.Activities.DeleteAsync(...) à l’aide de la méthode de l’infrastructure du SDK Teams.

Remarque

Un agent ne peut pas mettre à jour ou supprimer les messages envoyés par l’utilisateur dans Microsoft Teams.

Mettre à jour les messages

Vous pouvez utiliser des mises à jour de messages dynamiques pour des scénarios tels que les mises à jour de sondage, la modification des actions disponibles après une pression sur un bouton ou tout autre changement d’état asynchrone.

Il n’est pas nécessaire que le nouveau message corresponde au type d’origine. Par exemple, si le message d’origine contient une pièce jointe, le nouveau message peut être un message texte simple.

Exemple de référence du code

Pour mettre à jour un message existant, transmettez au contexte un nouvel Activity objet avec l’ID d’activité existant. 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);
});

Pour mettre à jour un message existant, transmettez un nouvel objet Activity avec l’ID d’activité existant à la méthode updateActivity de l’objet 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'
    });
});

Pour mettre à jour un message existant, transmettez un nouvel objet Activity avec l’ID d’activité existant à la méthode context.Api.Conversations.Activities.UpdateAsync(...) de la classe 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")
    )

Remarque

Vous pouvez développer des applications Teams dans n’importe quelle technologie de programmation web et appeler directement les API REST du service Bot Connector. Pour ce faire, vous devez mettre en œuvre des procédures de sécurité d'authentification avec vos demandes d'API.

Pour mettre à jour une activité existante dans une conversation, incluez les conversationId et activityId dans le point de terminaison de la requête. Pour effectuer ce scénario, vous devez mettre en cache l’ID d’activité retourné par l’appel de publication d’origine.

PUT /v3/conversations/{conversationId}/activities/{activityId}
Demande Réponse
Objet Activity . Objet ResourceResponse .

Maintenant que vous avez mis à jour les messages, mettez à jour la carte existante lors de la sélection du bouton pour les activités entrantes.

Mettre à jour les cartes

Pour mettre à jour la carte existante lors de la sélection du bouton, vous pouvez utiliser ReplyToId de l’activité entrante.

Exemple de référence du code

Pour mettre à jour la carte existante sur une sélection de bouton, transmettez un nouvel objet Activity avec la carte mise à jour et ReplyToId comme ID d’activité à la méthode context.Api.Conversations.Activities.UpdateAsync(...) de la classe 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);
});

Pour mettre à jour la carte existante sur une sélection de bouton, transmettez un nouvel objet Activity avec la carte mise à jour et replyToId comme ID d’activité à la méthode updateActivity de l’objet 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]
    });
});

Pour mettre à jour la carte existante sur un clic de bouton, passez un nouvel objet Activity avec la carte mise à jour et reply_to_id comme ID d’activité à la méthode ctx.api.conversations.activities(conversation_id).update(...) de la classe 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)
    )

Remarque

Vous pouvez développer des applications Teams dans n’importe quelle technologie de programmation web et appeler directement les API REST du service de connecteur de bot. Pour ce faire, vous devez implémenter procédures d’authentification de sécurité avec vos demandes d’API.

Pour mettre à jour une activité existante dans une conversation, incluez les conversationId et activityId dans le point de terminaison de la requête. Pour effectuer ce scénario, vous devez mettre en cache l’ID d’activité retourné par l’appel de publication d’origine.

PUT /v3/conversations/{conversationId}/activities/{activityId}
Demande Réponse
Objet d’activité. Objet ResourceResponse .

Maintenant que vous disposez de cartes mises à jour, vous pouvez supprimer des messages à l’aide de l’infrastructure du kit de développement logiciel (SDK) Teams.

Suppression de messages

Dans l’infrastructure du SDK Teams, chaque message a son identificateur d’activité unique. Les messages peuvent être supprimés context.Api.Conversations.Activities.DeleteAsync(...) à l’aide de la méthode de l’infrastructure du SDK Teams.

Exemple de référence du code

Pour supprimer un message, transmettez l’ID de cette activité à la méthode context.Api.Conversations.Activities.DeleteAsync(...) de la classe TurnContext.

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

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

Exemple de référence du code

Pour supprimer un message, transmettez l’ID de cette activité à la méthode context.Api.Conversations.Activities.DeleteAsync(...) de l’objet TurnContext.

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

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

Pour supprimer ce message, transmettez l’ID de cette activité à la méthode delete_activity de l’objet 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)

Pour supprimer une activité existante dans une conversation, incluez les conversationId et activityId dans le point de terminaison de la demande.

DELETE /v3/conversations/{conversationId}/activities/{activityId}
Requête et réponse Description
S/O Code d’état HTTP indiquant le résultat de l’opération. Rien n’est spécifié dans le corps de la réponse.

Réponses citées

Les réponses entre guillemets permettent à votre agent de faire référence à un message précédent de la conversation. Lorsqu’un utilisateur envoie un message qui cite un autre message, votre agent reçoit des métadonnées structurées sur le contenu cité. Votre agent peut également envoyer des messages qui citent des messages précédents.

Recevoir des réponses citées

Lorsqu’un utilisateur cite un message et l’envoie à votre agent, les métadonnées de réponse citées sont disponibles sur l’activité entrante. Utilisez cette GetQuotedMessages méthode pour accéder à toutes les entités de réponse entre guillemets.

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

Lorsqu’un utilisateur cite un message et l’envoie à votre agent, les métadonnées de réponse citées sont disponibles sur l’activité entrante. Utilisez cette getQuotedMessages méthode pour accéder à toutes les entités de réponse entre guillemets.

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

Lorsqu’un utilisateur cite un message et l’envoie à votre agent, les métadonnées de réponse citées sont disponibles sur l’activité entrante. Utilisez cette get_quoted_messages méthode pour accéder à toutes les entités de réponse entre guillemets.

@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}\""
        )

Envoyer des réponses citées

Lorsque votre agent appelle Reply(), le SDK tamponne automatiquement une entité de réponse citée faisant référence au message entrant. La réponse apparaîtra sous forme de réponse citée dans Teams.

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

Pour citer un autre message de la même conversation (pas le message entrant), utilisez la méthode avec l’ID Quote() de message que vous souhaitez citer.

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

Lorsque votre agent appelle reply(), le SDK tamponne automatiquement une entité de réponse citée faisant référence au message entrant. La réponse apparaîtra sous forme de réponse citée dans Teams.

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

Pour citer un autre message de la même conversation (pas le message entrant), utilisez la méthode avec l’ID quote() de message que vous souhaitez citer.

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

Lorsque votre agent appelle reply(), le SDK tamponne automatiquement une entité de réponse citée faisant référence au message entrant. La réponse apparaîtra sous forme de réponse citée dans Teams.

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

Pour citer un autre message de la même conversation (pas le message entrant), utilisez la méthode avec l’ID quote() de message que vous souhaitez citer.

@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")

Créez des réponses entre guillemets pour l’envoi proactif de messages

Pour les scénarios proactifs (avec app.Send()) ou lors de la citation de plusieurs messages, utilisez la AddQuote() méthode sur une activité de message. Transmettez l’ID de message et un texte de réponse facultatif.

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

Pour les scénarios proactifs (avec app.send()) ou lors de la citation de plusieurs messages, utilisez la addQuote() méthode sur une activité de message. Transmettez l’ID de message et un texte de réponse facultatif.

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

Pour les scénarios proactifs (avec app.send()) ou lors de la citation de plusieurs messages, utilisez la add_quote() méthode sur une activité de message. Transmettez l’ID de message et un texte de réponse facultatif.

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)

Envoyer des messages dans les données de canal Teams

L’objet channelData contient des informations spécifiques à Teams et constitue une source définitive pour les ID d’équipe et de canal. Si vous le souhaitez, vous pouvez mettre en cache et utiliser ces ID comme clés pour le stockage local. Le App dans le SDK extrait les informations importantes de l’objet channelData pour le rendre accessible. Toutefois, vous pouvez toujours accéder aux données d’origine à partir de l’objet turnContext .

L’objet channelData n’est pas inclus dans les messages de conversations personnelles, car celles-ci ont lieu en dehors d’un canal.

Un objet type channelData d’une activité envoyée à votre agent contient les informations suivantes :

  • eventType: type d’événement Teams transmis uniquement en cas d’événements de conversation dans votre agent Teams.
  • tenant.id: ID de locataire Microsoft Entra transmis dans tous les contextes.
  • team: Passé uniquement dans des contextes de canal, pas dans la conversation personnelle.
  • channel: passe uniquement dans des contextes de canal, lorsque l’agent est mentionné ou pour des événements dans des canaux d’équipes, où l’agent est ajouté.
  • channelData.teamsTeamId: Déconseillé. Cette propriété est incluse uniquement à des fins de rétrocompatibilité.
  • channelData.teamsChannelId: Déconseillé. Cette propriété est incluse uniquement à des fins de rétrocompatibilité.

Le code suivant montre un exemple d’objet channelData (événement 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"
    }
}

Données du canal Teams

L’objet channelData contient des informations spécifiques à Teams et constitue une source définitive pour les ID d’équipe et de canal. Si vous le souhaitez, vous pouvez mettre en cache et utiliser ces ID comme clés pour le stockage local. Le App dans le SDK extrait les informations importantes de l’objet channelData pour le rendre accessible. Toutefois, vous pouvez toujours accéder aux données d’origine à partir de l’objet turnContext .

L’objet channelData n’est pas inclus dans les messages de conversations personnelles, car celles-ci ont lieu en dehors d’un canal.

Un objet type channelData d’une activité envoyée à votre agent contient les informations suivantes :

  • eventType: type d’événement Teams passé uniquement en cas d’événements de modification de canal.
  • tenant.id: ID de locataire Microsoft Entra transmis dans tous les contextes.
  • team: Passé uniquement dans des contextes de canal, pas dans la conversation personnelle.
    • id: GUID du canal.
    • name: nom de l’équipe transmis uniquement dans les cas de (how-to/conversations/subscribe-to-conversation-events.md#team-renamed).
  • channel: passe uniquement dans des contextes de canal, lorsque l’agent est mentionné ou pour des événements dans des canaux d’équipes, où l’agent est ajouté.
  • channelData.teamsTeamId: Déconseillé. Cette propriété est incluse uniquement à des fins de rétrocompatibilité.
  • channelData.teamsChannelId: Déconseillé. Cette propriété est incluse uniquement à des fins de rétrocompatibilité.

Exemple d’objet channelData

Le code suivant montre un exemple d’objet channelData (événement 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"
    }
}

Codes d’état des API conversationnelles de l’agent

Assurez-vous de gérer ces erreurs de manière appropriée dans votre application Teams. Le tableau suivant répertorie les codes d’erreur et les descriptions sous lesquelles les erreurs sont générées :

Code d'état Code d’erreur et valeurs des messages Description Demande de nouvelle tentative Action du développeur
400 Code : Bad Argument
Message : *scénario spécifique
Charge utile de requête non valide fournie par l’agent. Pour plus de détails, consultez le message d’erreur. Non Réévaluez la charge utile de la requête pour les erreurs. Pour plus d’informations, consultez le message d’erreur renvoyé.
401 Code : BotNotRegistered
Message : Aucune inscription n’a été trouvée pour cet agent.
L’inscription de cet agent est introuvable. Non Vérifiez l’ID et le mot de passe de l’agent. Assurez-vous que l’ID du bot (Microsoft Entra ID) est inscrit dans le portail des développeurs Teams ou via l’inscription du canal du bot Azure dans Azure avec le canal « Teams » activé.
403 Code : BotDisabledByAdmin
Message : L’administrateur client a désactivé cet agent
L’Administration a bloqué les interactions entre l’utilisateur et l’application de l’agent. L’Administration doit autoriser l’application pour l’utilisateur à l’intérieur des stratégies d’application. Pour plus d’informations, consultez stratégies d’application. Non Arrêtez de publier dans la conversation jusqu’à ce que l’interaction avec l’agent soit explicitement lancée par un utilisateur dans la conversation indiquant que l’agent n’est plus bloqué.
403 Code : BotNotInConversationRoster
Message : L’agent ne fait pas partie de la liste de conversation.
L’agent ne fait pas partie de la conversation. L’application doit être réinstallée dans la conversation. Non Avant de tenter d’envoyer une autre demande de conversation, attendez un installationUpdate événement qui indique que l’agent est ajouté à nouveau.
403 Code : ConversationBlockedByUser
Message : l’utilisateur a bloqué la conversation avec l’agent.
L’utilisateur a bloqué l’agent dans une conversation personnelle ou un canal via les paramètres de modération. Non Supprimez la conversation du cache. Arrêtez d’essayer de publier dans les conversations jusqu’à ce que l’interaction avec l’agent soit explicitement lancée par un utilisateur dans la conversation, indiquant que l’agent n’est plus bloqué.
403 Code : ForbiddenOperationException
Message : L’agent n’est pas installé dans l’étendue personnelle de l’utilisateur
Le message proactif est envoyé par un agent, qui n’est pas installé dans une étendue personnelle. Non Avant de tenter d’envoyer une autre demande de conversation, installez l’application dans l’étendue personnelle.
403 Code : InvalidBotApiHost
Message : Hôte API de l’agent non valide. Pour les clients GCC, appelez .https://smba.infra.gcc.teams.microsoft.com
L’agent a appelé le point de terminaison d’API publique pour une conversation qui appartient à un client GCC. Non Mettez à https://smba.infra.gcc.teams.microsoft.com jour l’URL du service pour la conversation et relancez la demande.
403 Code : NotEnoughPermissions
Message : *scénario spécifique
L’agent ne dispose pas des autorisations nécessaires pour effectuer l’action demandée. Non Déterminez l’action requise à partir du message d’erreur.
404 Code : ActivityNotFoundInConversation
Message : Conversation introuvable.
L’ID de message fourni est introuvable dans la conversation. Le message n’existe pas ou est supprimé. Non Vérifiez si l’ID de message envoyé est une valeur attendue. Supprimez l’ID s’il a été mis en cache.
404 Code : ConversationNotFound
Message : Conversation introuvable.
La conversation est introuvable car elle n’existe pas ou a été supprimée. Non Vérifiez si l’ID de conversation envoyé est une valeur attendue. Supprimez l’ID s’il a été mis en cache.
412 Code : PreconditionFailed
Message : Échec de la condition préalable, réessayez.
Échec d’une condition préalable sur l’une de nos dépendances en raison de plusieurs opérations simultanées sur la même conversation. Oui Réessayez avec une interruption exponentielle.
413 Code : MessageSizeTooBig
Message : Taille du message trop grande.
La taille de la requête entrante était trop importante. Pour plus d’informations, consultez Formater les messages de votre agent. Non Réduire la taille de la charge utile.
429 Code : Throttled
Message : Trop de demandes. Retourne également le moment de réessayer après.
Trop de demandes envoyées par l’agent. Pour plus d’informations, voir Limite de débit. Oui Réessayez à l’aide de l’en-tête Retry-After pour déterminer le temps d’interruption.
500 Code : ServiceError
Message : *divers
Erreur interne au serveur. Non Signalez le problème dans la communauté des développeurs.
Forums de la communauté des développeurs.
502 Code : ServiceError
Message : *divers
Problème de dépendance au service. Oui Réessayez avec une interruption exponentielle. Si le problème persiste, signalez-le dans les forums de la communauté de développeurs.
503 Le service n’est pas disponible. Oui Réessayez avec une interruption exponentielle. Si le problème persiste, signalez-le à la communauté des développeurs.
504 Délai d’expiration de la passerelle. Oui Réessayez avec une interruption exponentielle. Si le problème persiste, signalez-le à la communauté des développeurs.

Code d’état : guide de nouvelle tentative

Les instructions générales relatives aux nouvelles tentatives pour chaque code de status sont répertoriées dans le tableau suivant. L’agent doit éviter de réessayer des codes de status qui ne sont pas spécifiés :

Code d'état Stratégie de nouvelle tentative
403 Nouvelle tentative en appelant l’API https://smba.infra.gcc.teams.microsoft.com GCC pour InvalidBotApiHost.
412 Réessayez à l’aide d’une interruption exponentielle.
429 Réessayez à l’aide Retry-After de l’en-tête pour déterminer le temps d’attente en secondes et entre les requêtes, le cas échéant. Dans le cas contraire, réessayez d’utiliser une interruption exponentielle avec l’ID de thread, si possible.
502 Réessayez à l’aide d’une interruption exponentielle.
503 Réessayez à l’aide d’une interruption exponentielle.
504 Réessayez à l’aide d’une interruption exponentielle.

En-têtes de requête de l’agent

Les requêtes sortantes actuelles à l’agent ne contiennent dans l’en-tête ou l’URL aucune information qui aide les agents à acheminer le trafic sans décompresser toute la charge utile. Les activités sont envoyées à l’agent via une URL similaire à https://< your_domain>/api/messages. Les demandes sont reçues pour afficher l’ID de conversation et l’ID de locataire dans les en-têtes.

Champs d’en-tête de demande

Deux champs d’en-tête de demande non standard sont ajoutés à toutes les demandes envoyées aux agents, pour le flux asynchrone et le flux synchrone. Le tableau suivant fournit les champs d’en-tête de demande et leurs valeurs :

Clé de champ Valeur
x-ms-conversation-id ID de conversation correspondant à l’activité de demande, le cas échéant, et confirmé ou vérifié.
x-ms-tenant-id ID de locataire correspondant à la conversation dans l’activité de demande.

Si l’ID de locataire ou de conversation n’est pas présent dans l’activité ou n’a pas été validé côté service, la valeur est vide.

L’image montre les champs d’en-tête.

Recevoir uniquement les messages mentionnés sur

Pour permettre à vos agents d’obtenir uniquement les messages de canal ou de chat où se trouve @mentionedvotre agent, vous devez filtrer les messages. Utilisez l’extrait de code suivant pour permettre à votre agent de ne recevoir que les messages où il est @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 vous souhaitez que votre agent reçoive tous les messages, vous n’avez pas besoin de filtrer les @mention messages.

Étape suivante

Conversations de canal et de groupe avec un agent

Voir aussi

Événements de conversation dans votre agent Teams