Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Os agentes de conversa se comunicam com os usuários por meio de mensagens, permitindo interações perfeitas. Ele pode simular conversas da vida real com usuários por meio de interações de texto ou voz. Você deve garantir que as conversas dos agentes sejam interativas, dinâmicas, adaptáveis e amigáveis.
Conteúdo da mensagem
A interação de mensagens entre seu agente e usuário pode incluir diferentes tipos de conteúdo de mensagem que:
| Tipo de conteúdo | Do usuário para o agente | Do agente para o usuário |
|---|---|---|
| Rich text e emojis | ✔️ | ✔️ |
| Imagens | ✔️ | ✔️ |
| Cartões Adaptáveis | ❌ | ✔️ |
Usar mensagem rich text e emojis
O agente do Teams pode enviar rich text e emojis. O Teams dá suporte a emojis por meio de UTF-16, como U+1F600 para um rosto sorridente.
Usar mensagens com imagem
Para fazer as mensagens do agente se destacarem, o usuário pode adicionar imagens como anexos:
As imagens podem ter até 1024 × 1024 pixels e 1 MB nos formatos PNG, JPEG ou GIF. Não há suporte para GIFs animados.
Você pode especificar a altura e a largura de cada imagem usando XML. Em Markdown, o tamanho da imagem é padrão como 256×256. Por exemplo:
- ✔️ :
<img src="http://aka.ms/Fo983c" alt="Duck on a rock" height="150" width="223"></img>. -
❌:
.
- ✔️ :
Para obter mais informações sobre anexos, consulte Adicionar anexos de mídia a mensagens.
Usar Cartões Adaptáveis
Um agente de conversa pode incluir Cartões Adaptáveis que simplificam os fluxos de trabalho de negócios. Os Cartões Adaptáveis oferecem texto, fala, imagens, botões e campos de entrada avançados e personalizáveis. Você pode criar Cartões Adaptáveis em um agente e mostrados em vários aplicativos, como Teams, seu site e assim por diante.
Para saber mais, confira:
- Cartões Adaptáveis.
- Referência de card do Teams para cartões com suporte.
O código a seguir mostra um exemplo de envio de um Cartão Adaptável simples:
Exemplo: enviar um Cartão Adaptável simples
{
"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 e receber mensagens
Enviar e receber mensagens é a principal funcionalidade de um agente.
Em um chat, cada mensagem é um Activity objeto do tipo messageType: message. Quando alguém envia uma mensagem, o Microsoft Teams a posta para o seu agente. O Teams envia um objeto JSON para o ponto de extremidade de mensagens do agente e permite apenas um ponto de extremidade para mensagens. Em seguida, seu agente verifica a mensagem para descobrir seu tipo e responde de acordo.
As conversas básicas são gerenciadas por meio do conector do Teams SDK Framework, que é uma API REST única. Essa API permite que seu agente fale com o Teams e outros canais. O SDK do Bot Builder oferece os seguintes recursos:
- Fácil acesso ao conector do SDK Framework do Teams.
- Ferramentas para gerenciar o fluxo e o estado da conversa.
- Maneiras simples de adicionar serviços cognitivos, como processamento de linguagem natural (PNL).
Seu agente recebe mensagens do Teams usando a Text propriedade e pode enviar respostas únicas ou múltiplas aos usuários.
Para obter mais informações, consulte atribuição de usuário para mensagens de agente.
A tabela a seguir lista a atividade que seu agente pode receber e executar uma ação:
| Tipo de mensagem | Objeto do conteúdo | Escopo |
|---|---|---|
| Receber uma atividade de mensagem | Atividade de mensagem | Todos |
| Receber atividade de edição de mensagem | Atividade de edição de mensagem | Todos |
| Receber atividade de mensagem de cancelamento de exclusão | Atividade de cancelamento de exclusão de mensagem | Todos |
| Receber atividade de mensagem de exclusão reversível | Atividade de exclusão temporária de mensagem | Todos |
Receber uma atividade de mensagem
Para receber uma mensagem de texto, use a Text propriedade de um Activity objeto. No manipulador de atividades do agente, use o objeto de contexto turn para ler uma única solicitação de Activity mensagem.
O código a seguir mostra um exemplo de recebimento de uma atividade de mensagem:
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"
}
Receber uma confirmação de leitura
A configuração de confirmação de leitura no Teams permite que o remetente de uma mensagem de chat seja notificado quando a mensagem for lida pelo destinatário em chats individuais e em grupo. Depois que o destinatário ler a mensagem, o Visto
aparecerá ao lado da mensagem. Você também tem a opção de configurar seu agente para receber eventos de confirmação de leitura por meio da configuração Confirmação de leitura . O evento de confirmação de leitura ajuda a aprimorar a experiência do usuário das seguintes maneiras:
Você poderá configurar seu agente para enviar uma mensagem de acompanhamento se o usuário do aplicativo não tiver lido a mensagem no chat pessoal.
Você pode criar um ciclo de feedback usando recibos de leitura para ajustar a experiência do seu agente.
Observação
- As confirmações de leitura só têm suporte em cenários de chat de usuário para agente.
- A confirmação de leitura para agentes não oferece suporte a escopos de equipe, canal e chat em grupo.
- Se um administrador ou usuário desabilitar a configuração de confirmação de leitura , o agente não receberá o evento de confirmação de leitura.
Para receber eventos de confirmação de leitura para seu agente, garanta o seguinte:
Adicione a permissão RSC
ChatMessageReadReceipt.Read.Chatno manifesto do aplicativo, da seguinte forma:"webApplicationInfo": { "id": "38f0ca43-1c38-4c39-8097e-47f62c686500", "resource": "" }, "authorization": { "permissions": { "orgwide": [], "resourceSpecific": [ { "name": "ChatMessageReadReceipt.Read.Chat", "type": "Application" } ] } }
Você também pode adicionar permissões RSC por meio da API do Graph. Para obter mais informações, confira consentedPermissionSet.
Substitua o método
OnReadReceiptporcontext.Activity.Value.LastReadMessageId.O
context.Activity.Value.LastReadMessageIdmétodo é útil para determinar se a mensagem é lida pelos destinatários. Se forcompareMessageIdmenor ou igual aLastReadMessageId, a mensagem foi lida. Substitua oOnReadReceiptmétodo para receber confirmações de leitura pelocontext.Activity.Value.LastReadMessageIdmétodo:app.OnReadReceipt(async context => { var lastReadMessageId = context.Activity.Value.LastReadMessageId; await context.Send("User read the agent's message"); });
O exemplo a seguir mostra uma solicitação de evento de confirmação de leitura recebida por um 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"
}
}
- A configuração de administrador de confirmação de leitura ou a configuração do usuário está ativada para o locatário para que o agente receba os eventos de confirmação de leitura. O administrador ou o usuário deve habilitar ou desabilitar a configuração de confirmação de leitura.
Depois que o agente é habilitado em um cenário de chat de usuário para agente, o agente recebe imediatamente um evento de confirmação de leitura quando o usuário lê a mensagem do agente. Você pode rastrear o envolvimento do usuário contando o número de eventos e também pode enviar uma mensagem com reconhecimento de contexto.
Receber atividade de edição de mensagem
Quando você edita uma mensagem, o agente recebe uma notificação da atividade de edição de mensagem.
Para obter uma notificação de atividade de mensagem de edição em um agente, você pode substituir o OnMessageEdit manipulador.
Veja a seguir um exemplo de uma notificação de atividade de edição de mensagem usando OnMessageEdit quando uma mensagem enviada é editada:
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 uma mensagem
Para enviar uma mensagem de texto, especifique a cadeia de caracteres que você deseja enviar como uma atividade. No manipulador de atividades do agente, use o método do objeto de contexto de turno context.Send(...) para enviar uma única resposta de mensagem. Use o método do multiple context.Send(...) calls objeto para enviar várias respostas.
O código a seguir mostra um exemplo de envio de uma mensagem quando um usuário é adicionado a uma conversa:
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"
}
Observação
- A divisão de mensagens ocorre quando uma mensagem de texto e um anexo são enviados no mesmo conteúdo de atividade. O Teams divide essa atividade em duas atividades separadas, uma com uma mensagem de texto e outra com um anexo. Como a atividade é dividida, você não recebe a ID da mensagem em resposta, que é usada para atualizar ou excluir a mensagem proativamente. É recomendável enviar atividades separadas em vez de depender da divisão de mensagens.
- As mensagens enviadas podem ser localizadas para fornecer personalização. Para obter mais informações, consulte localizar seu aplicativo.
As mensagens enviadas entre usuários e agentes incluem dados do canal interno dentro da mensagem. Esses dados permitem que o agente se comunique adequadamente nesse canal. O SDK do Bot Builder permite que você modifique a estrutura da mensagem.
Receber atividade de mensagem de cancelamento de exclusão
Quando você cancela a exclusão de uma mensagem, o agente recebe uma notificação da atividade de exclusão da mensagem.
Para obter uma notificação de atividade de mensagem de cancelamento de exclusão em um agente, você pode substituir o OnMessageUndelete manipulador.
Veja a seguir um exemplo de uma notificação de atividade de mensagem não excluída usando OnMessageUndelete quando uma mensagem excluída é restaurada:
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"
}
Receber atividade de mensagem de exclusão reversível
Quando você exclui temporariamente uma mensagem, o agente recebe uma notificação da atividade de mensagem de exclusão temporária.
Para obter uma notificação de atividade de mensagem de exclusão reversível em um agente, você pode substituir o OnMessageSoftDelete manipulador.
O exemplo a seguir mostra uma notificação de atividade de mensagem de exclusão reversível usando OnMessageSoftDelete quando uma mensagem é excluída temporariamente:
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"
}
Atualizar e excluir mensagens enviadas do agente
Importante
Os exemplos de código nesta seção são baseados na versão 4.6 e versões posteriores do SDK do Bot Framework. Se você estiver procurando documentação para versões anteriores, consulte a seção bots - v3 SDK na pasta SDKs herdados da documentação.
Seu agente pode atualizar mensagens dinamicamente depois de enviá-las, em vez de tê-las como instantâneos estáticos de dados. As mensagens também podem ser excluídas context.Api.Conversations.Activities.DeleteAsync(...) usando o método da Estrutura SDK do Teams.
Observação
Um agente não pode atualizar ou excluir mensagens enviadas pelo usuário no Microsoft Teams.
Atualizar mensagens
Você pode usar atualizações de mensagens dinâmicas para cenários, como atualizações de votação, modificação de ações disponíveis após um pressionamento de botão ou qualquer outra alteração de estado assíncrona.
Não é necessário que a nova mensagem corresponda ao tipo original. Por exemplo, se a mensagem original contiver um anexo, a nova mensagem poderá ser uma mensagem de texto simples.
Referência de código de exemplo
Para atualizar uma mensagem existente, passe um novo Activity objeto com a ID de atividade existente para o 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 atualizar uma mensagem existente, passe um novo objeto Activity com a ID de atividade existente para o método updateActivity do TurnContext objeto.
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 atualizar uma mensagem existente, passe um novo objeto Activity com a ID de atividade existente para o método context.Api.Conversations.Activities.UpdateAsync(...) da 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")
)
Observação
Você pode desenvolver aplicativos do Teams em qualquer tecnologia de programação da Web e chamar diretamente as APIs REST do serviço Bot Connector. Para fazer isso, você precisa implementar a Autenticação de segurança com suas solicitações de API.
Para atualizar uma atividade existente em uma conversa, inclua o conversationId e activityId no ponto de extremidade de solicitação. Para concluir esse cenário, você deve armazenar em cache a ID da atividade retornada pela pós-chamada original.
PUT /v3/conversations/{conversationId}/activities/{activityId}
| Solicitação | Resposta |
|---|---|
| Um objeto de Atividade. | Um objeto ResourceResponse. |
Agora que você atualizou as mensagens, atualize o cartão existente na seleção de botão para atividades de entrada.
Atualizar cartões
Para atualizar o cartão existente na seleção de botão, você pode usar ReplyToId atividade de entrada.
Referência de código de exemplo
Para atualizar o cartão existente em uma seleção de botão, passe um novo objeto Activity com cartão atualizado e ReplyToId como ID de atividade para o método context.Api.Conversations.Activities.UpdateAsync(...) da 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);
});
Para atualizar o cartão existente em uma seleção de botão, passe um novo objeto Activity com cartão atualizado e replyToId como ID de atividade para o método updateActivity do 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 atualizar o cartão existente com um clique de botão, passe um novo objeto Activity com o cartão atualizado e o reply_to_id como ID de atividade para o método ctx.api.conversations.activities(conversation_id).update(...) da 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)
)
Observação
Você pode desenvolver aplicativos do Teams em qualquer tecnologia de programação da Web e chamar diretamente as APIs REST de serviço de conector de bot. Para fazer isso, você deve implementar a autenticação de segurança com suas solicitações de API.
Para atualizar uma atividade existente em uma conversa, inclua o conversationId e activityId no ponto de extremidade de solicitação. Para concluir esse cenário, você deve armazenar em cache a ID da atividade retornada pela pós-chamada original.
PUT /v3/conversations/{conversationId}/activities/{activityId}
| Solicitação | Resposta |
|---|---|
| Um objeto de atividade. | Um objeto ResourceResponse. |
Agora que você atualizou os cartões, é possível excluir mensagens usando o SDK Framework do Teams.
Excluir mensagens
No Teams SDK Framework, cada mensagem tem seu identificador de atividade exclusivo. As mensagens podem ser excluídas context.Api.Conversations.Activities.DeleteAsync(...) usando o método da Estrutura SDK do Teams.
Referência de código de exemplo
Para excluir uma mensagem, passe a ID da atividade para o context.Api.Conversations.Activities.DeleteAsync(...) da 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);
}
});
Referência de código de exemplo
Para excluir uma mensagem, passe o ID dessa atividade para o método context.Api.Conversations.Activities.DeleteAsync(...) do 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 excluir essa mensagem, passe o ID dessa atividade para o método delete_activity do 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 excluir uma atividade existente em uma conversa, inclua o conversationId e activityId no ponto de extremidade da solicitação.
DELETE /v3/conversations/{conversationId}/activities/{activityId}
| Solicitação e resposta | Descrição |
|---|---|
| N/D | Um código de status HTTP que indica o resultado da operação. Nada é especificado no corpo da resposta. |
Respostas citadas
As respostas entre aspas permitem que o agente faça referência a uma mensagem anterior na conversa. Quando um usuário envia uma mensagem que cita outra mensagem, seu agente recebe metadados estruturados sobre o conteúdo citado. Seu agente também pode enviar mensagens que citam mensagens anteriores.
Receber respostas citadas
Quando um usuário cita uma mensagem e a envia ao seu agente, os metadados de resposta entre aspas estão disponíveis na atividade de entrada. Use o GetQuotedMessages método para acessar todas as entidades de resposta entre aspas.
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}\"");
}
});
Quando um usuário cita uma mensagem e a envia ao seu agente, os metadados de resposta entre aspas estão disponíveis na atividade de entrada. Use o getQuotedMessages método para acessar todas as entidades de resposta entre aspas.
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}"`
);
}
});
Quando um usuário cita uma mensagem e a envia ao seu agente, os metadados de resposta entre aspas estão disponíveis na atividade de entrada. Use o get_quoted_messages método para acessar todas as entidades de resposta entre aspas.
@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 respostas citadas
Quando o agente chama Reply(), o SDK carimba automaticamente uma entidade de resposta entre aspas que faz referência à mensagem de entrada. A resposta aparecerá como uma resposta entre aspas no Teams.
app.OnMessage(async context =>
{
// Reply() automatically quotes the inbound message
await context.Reply("Got it!");
});
Para citar uma mensagem diferente na mesma conversa (não a mensagem de entrada), use o Quote() método com a ID de mensagem que você deseja citar.
app.OnMessage(async context =>
{
// Quote a specific message by its ID
var parentMessageId = "1772050244572";
await context.Quote(parentMessageId, "Referencing an earlier message");
});
Quando o agente chama reply(), o SDK carimba automaticamente uma entidade de resposta entre aspas que faz referência à mensagem de entrada. A resposta aparecerá como uma resposta entre aspas no Teams.
app.on('message', async ({ reply }) => {
// reply() automatically quotes the inbound message
await reply('Got it!');
});
Para citar uma mensagem diferente na mesma conversa (não a mensagem de entrada), use o quote() método com a ID de mensagem que você deseja citar.
app.on('message', async ({ quote }) => {
// Quote a specific message by its ID
const parentMessageId = '1772050244572';
await quote(parentMessageId, 'Referencing an earlier message');
});
Quando o agente chama reply(), o SDK carimba automaticamente uma entidade de resposta entre aspas que faz referência à mensagem de entrada. A resposta aparecerá como uma resposta entre aspas no Teams.
@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]):
# reply() automatically quotes the inbound message
await ctx.reply("Got it!")
Para citar uma mensagem diferente na mesma conversa (não a mensagem de entrada), use o quote() método com a ID de mensagem que você deseja 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")
Crie respostas entre aspas para enviar mensagens de forma proativa
Para cenários proativos (usando app.Send()) ou ao citar várias mensagens, use o AddQuote() método em uma atividade de mensagem. Passe a ID da mensagem e um texto de resposta 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 cenários proativos (usando app.send()) ou ao citar várias mensagens, use o addQuote() método em uma atividade de mensagem. Passe a ID da mensagem e um texto de resposta 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 cenários proativos (usando app.send()) ou ao citar várias mensagens, use o add_quote() método em uma atividade de mensagem. Passe a ID da mensagem e um texto de resposta 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 mensagens nos dados do canal do Teams
O channelData objeto contém informações específicas do Teams e é uma fonte definitiva para IDs de equipe e canal. Opcionalmente, você pode armazenar em cache e usar essas IDs como chaves para armazenamento local. O App no SDK extrai informações importantes do channelData objeto para torná-lo acessível. No entanto, você sempre pode acessar os dados originais do turnContext objeto.
O channelData objeto não é incluído em mensagens em conversas pessoais, pois elas ocorrem fora de um canal.
Um objeto típico channelData em uma atividade enviada ao seu agente contém as seguintes informações:
-
eventType: O tipo de evento do Teams foi aprovado apenas em casos de eventos de conversa no seu agente do Teams. -
tenant.id: ID de locatário do Microsoft Entra passada em todos os contextos. -
team: Aprovada somente em contextos de canal, não no chat pessoal.-
id: GUID do canal. -
name: Nome da equipe passada apenas em casos de eventos de renomeação de equipe.
-
-
channel: Aprovado somente em contextos de canal, quando o agente é mencionado ou para eventos em canais no Teams, onde o agente é adicionado.-
id: GUID do canal. -
name: Nome do canal passado apenas em casos de eventos de modificação de canal.
-
-
channelData.teamsTeamId: Preterido. Essa propriedade só é incluída para compatibilidade com versões anteriores. -
channelData.teamsChannelId: Preterido. Essa propriedade só é incluída para compatibilidade com versões anteriores.
O código a seguir mostra um exemplo de objeto channelData (evento channelCreated):
"channelData": {
"eventType": "channelCreated",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
},
"channel": {
"id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype",
"name": "My New Channel"
},
"team": {
"id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype"
}
}
Dados do canal do Teams
O channelData objeto contém informações específicas do Teams e é uma fonte definitiva para IDs de equipe e canal. Opcionalmente, você pode armazenar em cache e usar essas IDs como chaves para armazenamento local. O App no SDK extrai informações importantes do channelData objeto para torná-lo acessível. No entanto, você sempre pode acessar os dados originais do turnContext objeto.
O channelData objeto não é incluído em mensagens em conversas pessoais, pois elas ocorrem fora de um canal.
Um objeto típico channelData em uma atividade enviada ao seu agente contém as seguintes informações:
-
eventType: o tipo de evento do Teams foi aprovado apenas em casos de eventos de modificação de canal. -
tenant.id: ID de locatário do Microsoft Entra passada em todos os contextos. -
team: Aprovada somente em contextos de canal, não no chat pessoal.-
id: GUID do canal. -
name: Nome da equipe passada somente em casos de (how-to/conversations/subscribe-to-conversation-events.md#team-renamed).
-
-
channel: Aprovado somente em contextos de canal, quando o agente é mencionado ou para eventos em canais no Teams, onde o agente é adicionado.-
id: GUID do canal. -
name: Nome do canal passado apenas em casos de eventos de modificação de canal.
-
-
channelData.teamsTeamId: Preterido. Essa propriedade só é incluída para compatibilidade com versões anteriores. -
channelData.teamsChannelId: Preterido. Essa propriedade só é incluída para compatibilidade com versões anteriores.
Exemplo de objeto channelData
O código a seguir mostra um exemplo de objeto channelData (evento channelCreated):
"channelData": {
"eventType": "channelCreated",
"tenant": {
"id": "72f988bf-86f1-41af-91ab-2d7cd011db47"
},
"channel": {
"id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype",
"name": "My New Channel"
},
"team": {
"id": "19:693ecdb923ac4458a5c23661b505fc84@thread.skype"
}
}
Códigos de status das APIs de conversa do agente
Certifique-se de lidar com esses erros adequadamente no aplicativo Teams. A tabela a seguir lista os códigos de erro e as descrições sob as quais os erros são gerados:
| Código de status | Valores de código de erro e mensagem | Descrição | Solicitação de nova tentativa | Ação do desenvolvedor |
|---|---|---|---|---|
| 400 |
Código: Bad Argument Mensagem: *específica do cenário |
Carga de solicitação inválida fornecida pelo agente. Consulte a mensagem de erro para obter detalhes específicos. | Não | Reavalie a carga de solicitação em busca de erros. Verifique a mensagem de erro retornada para obter detalhes. |
| 401 |
Código: BotNotRegistered Mensagem: Nenhum registro encontrado para este agente. |
O registro para este agente não foi encontrado. | Não | Verifique a ID e a senha do agente. Verifique se a ID do bot (Microsoft Entra ID) está registrada no Portal do Desenvolvedor do Teams ou por meio do registro do canal de bots do Azure no Azure com o canal "Teams" habilitado. |
| 403 |
Código: BotDisabledByAdmin Mensagem: O administrador do locatário desabilitou este agente |
Administração bloqueou as interações entre o usuário e o aplicativo agente. O Administração precisa permitir o aplicativo para o usuário dentro das políticas de aplicativo. Para obter mais informações, consulte políticas de aplicativo. | Não | Pare de postar na conversa até que a interação com o agente seja explicitamente iniciada por um usuário na conversa, indicando que o agente não está mais bloqueado. |
| 403 |
Código: BotNotInConversationRoster Mensagem: O agente não faz parte da lista de conversas. |
O agente não faz parte da conversa. O aplicativo precisa ser reinstalado na conversa. | Não | Antes de tentar enviar outra solicitação de conversa, aguarde um installationUpdate evento, que indica que o agente foi adicionado novamente. |
| 403 |
Código: ConversationBlockedByUser Mensagem: O usuário bloqueou a conversa com o agente. |
O usuário bloqueou o agente no chat pessoal ou em um canal por meio das configurações de moderação. | Não | Exclua a conversa do cache. Pare de tentar postar nas conversas até que a interação com o agente seja explicitamente iniciada por um usuário na conversa, indicando que o agente não está mais bloqueado. |
| 403 |
Código: ForbiddenOperationException Mensagem: O agente não está instalado no escopo pessoal do usuário |
A mensagem proativa é enviada por um agente, que não está instalado em um escopo pessoal. | Não | Antes de tentar enviar outra solicitação de conversa, instale o aplicativo no escopo pessoal. |
| 403 |
Código: InvalidBotApiHost Mensagem: Host de API de agente inválido. Para locatários do GCC, chame https://smba.infra.gcc.teams.microsoft.com. |
O agente chamou o endpoint da API pública para uma conversa que pertence a um locatário do GCC. | Não | Atualize a URL do serviço para https://smba.infra.gcc.teams.microsoft.com a qual a conversa e repita a solicitação. |
| 403 |
Código: NotEnoughPermissions Mensagem: *específica do cenário |
O agente não tem permissões necessárias para executar a ação solicitada. | Não | Determine a ação necessária na mensagem de erro. |
| 404 |
Código: ActivityNotFoundInConversation Mensagem: Conversa não encontrada. |
Não foi possível localizar a ID da mensagem fornecida na conversa. A mensagem não existe ou foi excluída. | Não | Verifique se a ID da mensagem enviada é um valor esperado. Remova a ID se ela estiver armazenada em cache. |
| 404 |
Código: ConversationNotFound Mensagem: Conversa não encontrada. |
A conversa não foi encontrada porque não existe ou foi excluída. | Não | Verifique se a ID da conversa enviada é um valor esperado. Remova a ID se ela estiver armazenada em cache. |
| 412 |
Código: PreconditionFailed Mensagem: Falha na pré-condição, tente novamente. |
Uma pré-condição falhou em uma de nossas dependências devido a várias operações simultâneas na mesma conversa. | Sim | Tente novamente com retirada exponencial. |
| 413 |
Código: MessageSizeTooBig Mensagem: Tamanho da mensagem muito grande. |
O tamanho da solicitação de entrada era muito grande. Para obter mais informações, consulte Formatar suas mensagens de agente. | Não | Reduza o tamanho da carga. |
| 429 |
Código: Throttled Mensagem: Muitas solicitações. Também retorna quando tentar novamente depois. |
Muitas solicitações enviadas pelo agente. Para obter mais informações, consulte limite de taxa. | Sim | Tente usar Retry-After novamente o cabeçalho para determinar o tempo de retirada. |
| 500 |
Código: ServiceError Mensagem: *vários |
Erro de servidor interno. | Não | Relate o problema na comunidade de desenvolvedores. |
| Fóruns da comunidade de desenvolvedores. | ||||
| 502 |
Código: ServiceError Mensagem: *vários |
Problema de dependência de serviço. | Sim | Tente novamente com retirada exponencial. Se o problema persistir, relate o problema nos fóruns da comunidade de desenvolvedores. |
| 503 | O serviço não está disponível. | Sim | Tente novamente com retirada exponencial. Se o problema persistir, relate o problema na comunidade de desenvolvedores. | |
| 504 | Tempo limite do gateway. | Sim | Tente novamente com retirada exponencial. Se o problema persistir, relate o problema na comunidade de desenvolvedores. |
Códigos de status Diretrizes de nova tentativa
As diretrizes gerais de repetição para cada código de status estão listadas na tabela a seguir, o agente deve evitar repetir códigos de status que não sejam especificados:
| Código de status | Estratégia de repetição |
|---|---|
| 403 | Tente novamente chamando a API https://smba.infra.gcc.teams.microsoft.com do GCC para InvalidBotApiHost. |
| 412 | Tente novamente usando a retirada exponencial. |
| 429 | Tente usar novamente o cabeçalho para Retry-After determinar o tempo de espera em segundos e entre solicitações, se disponível. Caso contrário, tente novamente usar a retirada exponencial com a ID do thread, se possível. |
| 502 | Tente novamente usando a retirada exponencial. |
| 503 | Tente novamente usando a retirada exponencial. |
| 504 | Tente novamente usando a retirada exponencial. |
Cabeçalhos de solicitação do agente
As solicitações de saída atuais para o agente não contêm no cabeçalho ou URL nenhuma informação que ajude os agentes a rotear o tráfego sem descompactar todo o conteúdo. As atividades são enviadas ao agente por meio de uma URL semelhante a https://< your_domain>/api/messages. As solicitações são recebidas para mostrar o ID da conversa e o ID do locatário nos cabeçalhos.
Campos de cabeçalho de solicitação
Dois campos de cabeçalho de solicitação não padrão são adicionados a todas as solicitações enviadas aos agentes, tanto para fluxo assíncrono quanto para fluxo síncrono. A tabela a seguir fornece os campos de cabeçalho de solicitação e seus valores:
| Chave de campo | Valor |
|---|---|
| x-ms-conversation-id | O ID da conversa correspondente à atividade de solicitação, se aplicável e confirmado ou verificado. |
| x-ms-tenant-id | O ID do locatário correspondente à conversa na atividade de solicitação. |
Se o locatário ou a ID da conversa não estiver presente na atividade ou não tiver sido validada no lado do serviço, o valor estará vazio.
Receber apenas mensagens mencionadas
Para permitir que seus agentes recebam apenas as mensagens de canal ou chat em que seu agente está @mentioned, você deve filtrar as mensagens. Use o trecho de código a seguir para permitir que o agente receba somente as mensagens em que estiver @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.");
});
Se você quiser que seu agente receba todas as mensagens, não será necessário filtrar as @mention mensagens.
Próxima etapa
Conversas de chat de canal e grupo com um agente