Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. 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 Enviar mensagens e anexos.
Observação
Em ambientes GCC High e DoD, insira imagens em mensagens ou cartões de bot como conteúdo codificado em base64 porque os links de imagem externos não podem ser renderizados. Para obter detalhes, consulte Limites e especificações para o Microsoft Teams.
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.
Limites de tamanhos de mensagens
O limite de tamanho da mensagem do agente é de 100 KB. Esse é um limite aproximado porque inclui a própria mensagem (texto, links de imagem etc.), @-menções e reações codificadas como UTF-16. A limitação de tamanho de 100 KB não inclui imagens codificadas em base64. Durante a implementação, verifique se o tamanho da mensagem em si está dentro de 80 KB para garantir a entrega bem-sucedida da mensagem.
Se a mensagem do agente exceder o limite de tamanho, o agente receberá um código de 413 status (RequestEntityTooLarge), que contém o código MessageSizeTooBigde erro .
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 SDK do Teams, que lida com o protocolo de atividade entre seu agente e o Teams. O SDK do Teams oferece os seguintes recursos:
- Manipuladores de atividade digitados para mensagens e eventos de entrada.
- Ferramentas para gerenciar o fluxo e o estado da conversa.
- Um cliente de API do Teams para enviar, atualizar e excluir atividades.
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 a propriedade do objeto de contexto de Activity atividade para ler uma única solicitação de mensagem.
O código a seguir mostra um exemplo de recebimento de uma atividade de mensagem:
teams.OnMessage(async (context, cancellationToken) =>
{
await context.SendAsync($"Echo: {context.Activity.Text}", cancellationToken);
});
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-8097-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:
teams.OnReadReceipt(async (context, cancellationToken) =>
{
var lastReadMessageId = context.Activity.Value.LastReadMessageId;
await context.SendAsync("User read the agent's message", cancellationToken);
});
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 edição de mensagem em um agente, registre o OnMessageUpdate manipulador.
Veja a seguir um exemplo de uma notificação de atividade de edição de mensagem usando OnMessageUpdate quando uma mensagem enviada é editada:
teams.OnMessageUpdate(async (context, cancellationToken) =>
{
var eventType = context.Activity.ChannelData?.EventType;
if (eventType == "editMessage")
await context.SendAsync("message is updated", cancellationToken);
else if (eventType == "undeleteMessage")
await context.SendAsync("message is undeleted", cancellationToken);
});
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://smba.trafficmanager.net/amer/",
"from": {
"id":"29:1BLjP9j3_PM4mubmQZsYPx7jDyLeLf_YVA9sVPV08KMAFMjJWB_EUGveb9EVDh9TslNp9qjnzEBy3kgw01Jf1Kg",
"name":"Mike Wilber",
"aadObjectId":"520e4d1e-2108-43ee-a092-46a9507c6200"
},
"conversation":{
"conversationType":"personal",
"tenantId":"528dbe3f-15e0-4e37-84a1-00cc305847dd","id":"a:1pweuGJ44RkB90tiJNQ_I6g3vyuP4CYA_f-v6f0Vd-Bs3Ce85C73Ah1y8TvyjESsTHWjjgw-gnsuIuCUOWkfOCq6qaUYsk2_-fj93XXXHUMAUzhFFvTnaCU7V4WiMqRPB"
},
"recipient":{
"id":"28:0d569679-ab4c-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.SendAsync(...) para enviar uma única resposta de mensagem. Use o método do multiple context.SendAsync(...) 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:
teams.OnMembersAdded(async (context, cancellationToken) =>
{
foreach (var member in context.Activity.MembersAdded)
{
if (member.Id != context.Activity.Recipient.Id)
{
await context.SendAsync("Hello and welcome!", cancellationToken);
}
}
});
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 Teams 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.
As atividades de recuperação chegam por meio do manipulador no SDK do OnMessageUpdate Teams 2.1.0.
Veja a seguir um exemplo de uma notificação de atividade de mensagem não excluída quando uma mensagem excluída é restaurada:
teams.OnMessageUpdate(async (context, cancellationToken) =>
{
if (context.Activity.ChannelData?.EventType == "undeleteMessage")
{
await context.SendAsync("message is undeleted", cancellationToken);
}
});
Observação
No SDK do Teams 2.1, todos os manipuladores correspondentes são executados em sequência. Se você já manipula undeleteMessage o OnMessageUpdate manipulador mostrado na atividade Receber edição de mensagem, não registre esse manipulador também ou seu agente responde duas vezes.
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://smba.trafficmanager.net/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.
As atividades de exclusão temporária chegam por meio do manipulador no SDK do OnMessageDelete Teams 2.1.0.
O exemplo a seguir mostra uma notificação de atividade de mensagem de exclusão reversível quando uma mensagem é excluída temporariamente:
teams.OnMessageDelete(async (context, cancellationToken) =>
{
var eventType = context.Activity.ChannelData?.EventType;
if (eventType == "softDeleteMessage")
await context.SendAsync("message is soft deleted", cancellationToken);
});
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://smba.trafficmanager.net/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
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 usando o método SDK do Teams context.Api.Conversations.Activities.DeleteAsync(...) .
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'.
teams.OnMessage(async (context, cancellationToken) =>
{
// Send initial message
var response = await context.SendAsync("Your Message", cancellationToken);
var conversationId = context.Activity.Conversation.Id;
var activityId = response.Id;
var updatedActivity = new MessageActivityInput().WithText("The new text for the activity");
await context.Api.Conversations.Activities.UpdateAsync(conversationId, activityId, updatedActivity, cancellationToken);
});
Para atualizar uma mensagem existente, passe um novo Activity objeto com a ID de atividade existente para o api.conversations.activities(conversationId).update(...) método do objeto de contexto de atividade.
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 ctx.api.conversations.activities(conversation_id).update(...) do ActivityContext objeto.
@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 os pontos de extremidade REST de mensagens do Teams diretamente. Para fazer isso, você deve implementar procedimentos de segurança de autenticação com suas solicitações de API. Para obter mais informações, consulte Cliente de API do Teams.
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 Activity objeto. |
Um ResourceResponse objeto. |
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.
teams.OnMessage(async (context, cancellationToken) =>
{
var conversationId = context.Activity.Conversation.Id;
var activityId = context.Activity.ReplyToId;
TeamsAttachment attachment = TeamsAttachment.CreateBuilder()
.WithAdaptiveCard(JsonSerializer.SerializeToElement(card))
.Build();
var updatedActivity = new MessageActivityInput().AddAttachment(attachment);
await context.Api.Conversations.Activities.UpdateAsync(conversationId, activityId, updatedActivity, cancellationToken);
});
Para atualizar o card existente em uma seleção de botão, passe um novo Activity objeto com card atualizado e replyToId como ID de atividade para o api.conversations.activities(conversationId).update(...) método do objeto de contexto de atividade.
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 em uma seleção de botão, passe um novo objeto Activity com cartão atualizado e reply_to_id como ID de atividade para o método ctx.api.conversations.activities(conversation_id).update(...) do objeto ActivityContext.
@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 os pontos de extremidade REST de mensagens do Teams diretamente. Para fazer isso, você deve implementar a autenticação de segurança com suas solicitações de API. Para obter mais informações, consulte Cliente de API do Teams.
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 activity objeto. |
Um ResourceResponse objeto. |
Agora que você atualizou os cartões, poderá excluir mensagens usando o SDK do Teams.
Excluir mensagens
No SDK do Teams, cada mensagem tem seu identificador de atividade exclusivo. As mensagens podem ser excluídas usando o context.Api.Conversations.Activities.DeleteAsync(...) método.
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.
teams.OnMessage(async (context, cancellationToken) =>
{
var conversationId = context.Activity.Conversation.Id;
foreach (var activityId in _list)
{
await context.Api.Conversations.Activities.DeleteAsync(conversationId, activityId, cancellationToken);
}
});
Referência de código de exemplo
Para excluir uma mensagem, passe a ID dessa atividade para o api.conversations.activities(conversationId).delete(...) método do objeto de contexto de atividade.
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 ctx.api.conversations.activities(conversation_id).delete(...) do objeto ActivityContext.
@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.
teams.OnMessage(async (context, cancellationToken) =>
{
var quotes = context.Activity.GetQuotedMessages();
if (quotes.Count > 0)
{
var quote = quotes[0].QuotedReply;
await context.ReplyAsync(
$"You quoted message {quote.MessageId} from {quote.SenderName}: \"{quote.Preview}\"", cancellationToken);
}
});
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.
teams.OnMessage(async (context, cancellationToken) =>
{
// ReplyAsync() automatically quotes the inbound message
await context.ReplyAsync("Got it!", cancellationToken);
});
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.
teams.OnMessage(async (context, cancellationToken) =>
{
// Quote a specific message by its ID
var parentMessageId = "1772050244572";
await context.QuoteAsync(parentMessageId, "Referencing an earlier message", cancellationToken);
});
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 teams.SendAsync()) 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 MessageActivityInput()
.WithText("Here is my response")
.AddQuote(parentMessageId);
await teams.SendAsync(conversationId, msg, cancellationToken: cancellationToken);
// Multiple quotes with interleaved responses
msg = new MessageActivityInput()
.WithText("response to first")
.AddQuote(firstMessageId)
.AddQuote(secondMessageId, "response to second");
await teams.SendAsync(conversationId, msg, cancellationToken: cancellationToken);
// Grouped quotes — omit response to group quotes together
msg = new MessageActivityInput()
.WithText("see below for previous messages")
.AddQuote(firstMessageId)
.AddQuote(secondMessageId, "response to both");
await teams.SendAsync(conversationId, msg, cancellationToken: cancellationToken);
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)
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 objeto de contexto da atividade.
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 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. -
app: Disponível em conversas individuais (aplicativo pessoal). Contém a ID do aplicativo e a versão de manifesto instalada do aplicativo associado à atividade. Em alguns cenários,channelData.appisso pode não ser fornecido, como quando o agente não está instalado para o usuário ou quando vários aplicativos são mapeados para uma única ID de bot. Seu agente deve lidar com o caso em que esse campo está ausente.-
id: a ID do aplicativo. -
version: a versão do manifesto do aplicativo instalado.
-
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 no repositório do SDK do Teams. |
| 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 no repositório do SDK do Teams. |
| 503 | O serviço não está disponível. | Sim | Tente novamente com retirada exponencial. Se o problema persistir, relate o problema no repositório do SDK do Teams. | |
| 504 | Tempo limite do gateway. | Sim | Tente novamente com retirada exponencial. Se o problema persistir, relate o problema no repositório do SDK do Teams. |
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:
teams.OnMessage(async (context, cancellationToken) =>
{
if (!context.Activity.GetMentions().Any(mention => mention.Mentioned.Id.Equals(context.Activity.Recipient.Id, StringComparison.OrdinalIgnoreCase)))
{
return;
}
await context.SendAsync("Using RSC the agent can receive messages across channels or chats in team without being @mentioned.", cancellationToken);
});
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