Compartilhar via


Extensão de mensagem baseada em API

Observação

As extensões de mensagens baseadas em API só suportam comandos de pesquisa.

As extensões de mensagens criadas com a API (baseada em API) utilizam um serviço Web para gerir pedidos e respostas de utilizadores e não necessitam de um registo de bot. As extensões de mensagens baseadas em API são uma capacidade de aplicação do Microsoft Teams que integra APIs externas diretamente no Teams, melhorando a usabilidade da sua aplicação e oferecendo uma experiência de utilizador totalmente integrada. As extensões de mensagens baseadas em API suportam comandos de pesquisa e podem ser utilizadas para obter e apresentar dados de serviços externos no Teams, simplificando os fluxos de trabalho ao reduzir a necessidade de alternar entre aplicações. As extensões de mensagens baseadas em API ajudam as suas aplicações a interagir diretamente com dados, aplicações e serviços de terceiros, melhorando as suas capacidades. Com a extensão de mensagens baseada em API, pode:

  • Obtenha informações em tempo real, como a cobertura de notícias mais recente num lançamento de produto.
  • Obter informações baseadas em conhecimento, por exemplo, os ficheiros de design da minha equipa no Figma

Veja o vídeo para saber mais sobre a criação de uma extensão de mensagem baseada em API com o Teams Toolkit:


Extensões de mensagens tradicionais baseadas em bots Extensões de mensagens baseadas em API
Os programadores precisam de criar, implementar e manter um serviço para processar comandos de invocação do cliente do Teams. Se as APIs do serviço final puderem ser descritas com a Especificação openAPI, os programadores podem eliminar a necessidade do serviço de processamento de camada média.
Este serviço processa a consulta recebida e faz uma chamada para o serviço final do programador. O Teams pode utilizar diretamente a Especificação openAPI para criar pedidos e comunicar com o serviço final do programador.

As imagens seguintes mostram o fluxo de consultas do utilizador através de extensões de mensagens tradicionais e extensões de mensagens da API:

Captura de ecrã a mostrar o fluxo de consulta do utilizador entre um utilizador, o Cliente do Teams e o serviço de bot do Teams com extensões de mensagens tradicionais. O diagrama também mostra como a especificação da API, os modelos de composição, a API se relacionam entre si. Fluxo de consulta do utilizador com extensões de mensagens tradicionais. O programador tem de manter um serviço de processador de bots personalizado, que processa os pedidos de um bot do Teams. O serviço de processador envia um pedido ao serviço do programador quando uma consulta é invocada.


Captura de ecrã a mostrar o fluxo de consulta entre um utilizador, o Cliente do Teams e o serviço de bot do Teams através das Extensões de Mensagens da API. O diagrama também mostra como a especificação da API, os modelos de composição, a API se relacionam entre si. Fluxo de consulta de utilizador com Extensões de Mensagens de API. Não é necessário um serviço de processador mantido pelo programador, desde que a interação esteja claramente descrita na Especificação OpenAPI no Pacote de Aplicações.



Eis uma sequência de eventos de alto nível que ocorre durante uma invocação de comandos de consulta:

  1. Quando um utilizador invoca um comando de consulta, os parâmetros do comando de consulta são recebidos pela Serviço de Bot do Teams.

  2. O comando de consulta é definido dentro do ficheiro de manifesto da aplicação. A definição de comando contém uma referência ao operationId ficheiro OpenAPI Specification, juntamente com os detalhes dos parâmetros que o cliente do Teams compõe para esse comando. Para referência, o operationId ficheiro OpenAPI Specification no interior é exclusivo de uma determinada operação HTTP.

  3. O Teams Serviço de Bot, em seguida, utiliza os parâmetros fornecidos pelo utilizador juntamente com a cópia da Especificação openAPI para o associado operationId para criar um pedido HTTP para o ponto final do programador.

  4. Se a autenticação for necessária e estiver configurada no manifesto. É resolvido para o token ou chave adequado. Este token ou chave é utilizado como parte do pedido de saída. [Opcionalmente]

  5. O serviço de bot do Teams efetua o pedido HTTP ao serviço do programador.

  6. O serviço do programador deve responder de acordo com o esquema descrito na Especificação openAPI. Isto está no formato JSON.

  7. O cliente do Teams tem de mostrar os resultados ao utilizador. Para converter os resultados JSON do passo anterior para a IU, o serviço de bot do Teams utiliza o modelo de Composição de resposta para criar um Cartão Ajustável para cada resultado.

  8. Os Cartões Ajustáveis são enviados para o cliente, o que os compõe na IU.

O diagrama mostra o fluxo de sequência de alto nível quando uma consulta é invocada numa extensão de mensagem baseada em API.

Pré-requisitos

O pacote de definição de aplicação inclui vários artefactos apelativos que suportam a funcionalidade desta funcionalidade. Antes de começar, certifique-se de que tem uma compreensão básica dos seguintes ficheiros:

Descrição de OpenAPI (OAD)

O documenat de descrição de OpenAPI é um padrão da indústria adotado para descrever as APIs. Permite-lhe abstrair as SUAS APIs da respetiva implementação, fornecendo definições agnósticas de linguagem que são legíveis por humanos e legíveis por computador. A descrição openAPI descreve as interações que a sua extensão suporta, permitindo ao Teams criar pedidos e comunicar diretamente com o seu serviço sem a necessidade de um serviço de processamento de camada média.

Um documento de descrição openAPI contém detalhes para comunicar com o serviço do programador. Certifique-se de que cumpre as seguintes diretrizes para o documento de Descrição de OpenAPI (OAD):

  • As versões OpenAPI 2.0 e 3.0.x são suportadas.
  • JSON e YAML são os formatos suportados.
  • O corpo do pedido, se estiver presente, tem de ser application/Json.
  • Defina um URL de servidor de protocolo HTTPS para a servers.url propriedade .
  • Apenas os métodos POST e GET HTTP são suportados.
  • O documento Descrição de OpenAPI tem de ter um operationId.
  • Só é permitido um parâmetro necessário sem um valor predefinido.
  • Um parâmetro necessário com um valor predefinido é considerado opcional.
  • Os utilizadores não podem introduzir um parâmetro para um cabeçalho ou cookie.
  • A operação não pode ter um cabeçalho ou parâmetros de cookie necessários sem valores predefinidos.
  • Certifique-se de que não existem referências remotas no documento Descrição de OpenAPI.
  • A construção de matrizes para o pedido não é suportada; no entanto, os objetos aninhados dentro de um corpo de pedido JSON são suportados.
  • O Teams não suporta as oneOfconstruções , anyOf, allOfe not (swagger.io).

O código seguinte é um exemplo de um documento de Descrição de OpenAPI:

Documento de Descrição de OpenAPI de Exemplo
openapi: 3.0.1
info:
title: OpenTools Plugin
description: A plugin that allows the user to find the most appropriate AI tools for their use cases, with their pricing information.
version: 'v1'
servers:
- url: https://gptplugin.opentools.ai
paths:
/tools:
 get:
   operationId: searchTools
   summary: Search for AI Tools
   parameters:
     - in: query
       name: search
       required: true
       schema:
         type: string
       description: Used to search for AI tools by their category based on the keywords. For example, ?search="tool to create music" will give tools that can create music.
   responses:
     "200":
       description: OK
       content:
         application/json:
           schema:
             $ref: '#/components/schemas/searchToolsResponse'
     "400":
       description: Search Error
       content:
         application/json:
           schema:
             $ref: '#/components/schemas/searchToolsError'
components:
schemas:
 searchToolsResponse:
   required:
     - search
   type: object
   properties:
     tools:
       type: array
       items:
         type: object
         properties:
           name:
             type: string
             description: The name of the tool.
           opentools_url:
             type: string
             description: The URL to access the tool.
           main_summary:
             type: string
             description: A summary of what the tool is.
           pricing_summary:
             type: string
             description: A summary of the pricing of the tool.
           categories:
             type: array
             items:
               type: string
             description: The categories assigned to the tool.
           platforms:
             type: array
             items:
               type: string
             description: The platforms that this tool is available on.
       description: The list of AI tools.
 searchToolsError:
   type: object
   properties:
     message:
       type: string
       description: Message of the error.

Para obter mais informações sobre como escrever definições openAPI no YAML, veja Estrutura openAPI.

Manifesto do aplicativo

O manifesto de aplicação é um esquema para a sua aplicação Teams, que define como e onde a extensão de mensagem é invocada no cliente do Teams. Inclui os comandos suportados pela extensão e as localizações a partir das quais podem ser acedidos, como a área de composição de mensagens, a barra de comandos e a mensagem. O manifesto liga à Especificação OpenAPI e ao Modelo de Composição de Resposta para garantir a funcionalidade adequada.

O manifesto da aplicação contém a definição do comando de consulta. Certifique-se de que cumpre as seguintes diretrizes para o manifesto da aplicação:

  • Defina a versão do manifesto da aplicação como 1.17.
  • Defina composeExtensions.composeExtensionType como apiBased.
  • Defina composeExtensions.apiSpecificationFile como o caminho relativo para o documento Descrição de OpenAPI na pasta. Isto liga o manifesto da aplicação à especificação da API.
  • Defina apiResponseRenderingTemplateFile como o caminho relativo para o modelo de composição de resposta. Isto especifica a localização do modelo utilizado para compor respostas da API.
  • Cada comando tem de ter uma ligação para o modelo de composição de resposta. Esta ação liga cada comando ao respetivo formato de resposta correspondente.
  • A Commands.id propriedade no manifesto da aplicação tem de corresponder ao operationId no documento Descrição de OpenAPI.
  • Se um parâmetro necessário não tiver um valor predefinido, o comando parameters.name no manifesto da aplicação tem de corresponder ao parameters.name no documento de descrição OpenAPI.
  • Se não existir nenhum parâmetro necessário, o comando parameters.name no manifesto da aplicação tem de corresponder ao opcional parameters.name no documento Descrição de OpenAPI.
  • Certifique-se de que o nome dos parâmetros para cada comando no manifesto da aplicação corresponde exatamente ao nome correspondente do parâmetro definido para a operação no documento Descrição de OpenAPI.
  • Um modelo de composição de resposta tem de ser definido por comando, que é utilizado para converter respostas de uma API.
  • As descrições do comando e dos parâmetros não podem exceder os 128 carateres.

Segue-se um exemplo de manifesto de aplicação com definições para extensões de mensagens baseadas em API:

Exemplo de manifesto de aplicação
 {
 "$schema": "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.schema.json",
 +  "manifestVersion": "devPreview",
 "version": "1.0.0",
 "id": "04805b4b-xxxx-xxxx-xxxx-4dbc1cac8f89",
 "packageName": "com.microsoft.teams.extension",
 "developer": {
    "name": "Teams App, Inc.",
    "websiteUrl": "https://www.example.com",
    "privacyUrl": "https://www.example.com/termofuse",
    "termsOfUseUrl": "https://www.example.com/privacy"
 },
 "icons": {
    "color": "color.png",
    "outline": "outline.png"
 },
 "name": {
    "short": "AI tools",
    "full": "AI tools"
 },
 "description": {
    "short": "AI tools",
    "full": "AI tools"
 },
 "accentColor": "#FFFFFF",
 "composeExtensions": [
    {
 +      "composeExtensionType": "apiBased",
 +      "authorization": {
 +        "authType": "apiSecretServiceAuth ",
 +        "apiSecretServiceAuthConfiguration": {
 +            "apiSecretRegistrationId": "96270b0f-7298-40cc-b333-152f84321813"
 +        }
 +      },
 +      "apiSpecificationFile": "aitools-openapi.yml",
       "commands": [
       {
          "id": "searchTools",
          "type": "query",
          "context": [
             "compose",
             "commandBox"
          ],
          "title": "search for AI tools",
          "description": "search for AI tools",
          "parameters": [
             {
             "name": "search",
             "title": "search query",
             "description": "e.g. search='tool to create music'"
             }
          ],
 +          "apiResponseRenderingTemplateFile": "response-template.json"
       }
       ]
    }
 ],
 "validDomains": []
 }

Parâmetros

Nome Descrição
composeExtensions.composeExtensionType Compose tipo de extensão. Atualize o valor para apiBased.
composeExtensions.authorization Informações relacionadas com autorização para a extensão de mensagens baseada em API
composeExtensions.authorization.authType Enumeração de possíveis tipos de autorização. Os valores suportados são none, apiSecretServiceAuthe microsoftEntra.
composeExtensions.authorization.apiSecretServiceAuthConfiguration Objeto que captura os detalhes necessários para realizar a autenticação do serviço. Aplicável apenas quando o tipo de autenticação for apiSecretServiceAuth.
composeExtensions.authorization.apiSecretServiceAuthConfiguration.apiSecretRegistrationId ID de registo devolvido quando o programador submete a chave de API através do Portal do Programador.
composeExtensions.apiSpecificationFile Referencia um ficheiro de Descrição de OpenAPI no pacote de aplicação. Incluir quando o tipo for apiBased.
composeExtensions.commands.id ID exclusivo que atribui ao comando de pesquisa. A solicitação do usuário inclui essa ID. O ID tem de corresponder ao operationId disponível na Descrição de OpenAPI.
composeExtensions.commands.context Matriz onde os pontos de entrada para a extensão de mensagem estão definidos. Os valores predefinidos são compose e commandBox.
composeExtensions.commands.parameters Define uma lista estática de parâmetros para o comando . O nome tem de ser mapeado para na parameters.name Descrição de OpenAPI. Se estiver a referenciar uma propriedade no esquema do corpo do pedido, o nome tem de mapear para properties.name ou consultar parâmetros.
composeExtensions.commands.apiResponseRenderingTemplateFile Modelo utilizado para formatar a resposta JSON da API do programador para a resposta do Cartão Ajustável. [Obrigatório]

Para obter mais informações, veja composeExtensions.

Modelo de composição de resposta

Observação

O Teams suporta Cartões Ajustáveis até à versão 1.5. Ao utilizar o Estruturador de Cartões Ajustáveis, certifique-se de que altera a versão de destino para 1.5.

O modelo de composição de respostas é um formato predefinido que dita a forma como os resultados da sua API são apresentados no Teams. Utiliza modelos para criar Cartões Ajustáveis ou outros elementos de IU a partir da resposta da API, garantindo uma experiência de utilizador integrada e integrada no Teams. O modelo define o esquema e o estilo das informações apresentadas, que podem incluir texto, imagens e componentes interativos. Certifique-se de que cumpre as seguintes diretrizes para o modelo de composição de respostas:

  • Defina o URL de referência de esquema na $schema propriedade para estabelecer a estrutura do modelo para o esquema do modelo de composição de resposta.
  • Os valores suportados para responseLayout são list e grid, que determinam como a resposta é apresentada visualmente. Para obter mais informações sobre o esquema, veja Responder a pedidos de utilizador.
  • A jsonPath é necessário para matrizes ou quando os dados do Cartão Ajustável não são o objeto raiz. Por exemplo, se os seus dados estiverem aninhados em productDetails, o caminho JSON seria productDetails.
  • Defina jsonPath como o caminho para os dados ou matriz relevantes na resposta da API. Se o caminho apontar para uma matriz, cada entrada na matriz vincula-se ao modelo Cartão Ajustável e devolve como um resultado separado. [Opcional]
  • Obtenha uma resposta de exemplo para validar o modelo de composição de resposta. Isto serve como um teste para garantir que o seu modelo funciona conforme esperado.
  • Utilize ferramentas como o Fiddler ou o Postman para chamar a API e garantir que o pedido e a resposta são válidos. Este passo é crucial para resolver problemas e confirmar que a API está a funcionar corretamente.
  • Pode utilizar o cartão ajustável Designer para vincular a resposta da API ao modelo de composição de resposta e pré-visualizar o Cartão Ajustável. Insira o modelo Cartão Ajustável no EDITOR DE PAYLOAD CARTÃO e insira a entrada de resposta de exemplo no EDITOR DE DADOS DE EXEMPLO.

O código seguinte é um exemplo de um modelo de composição de Resposta:

Exemplo de modelo de composição de resposta
{
"version": "1.0",
"$schema": "developer.microsoft.com/json-schemas/teams/v1.17/MicrosoftTeams.ResponseRenderingTemplate.schema.json",
"jsonPath": "repairs",
"responseLayout": "grid",
"responseCardTemplate": {
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "type": "AdaptiveCard",
  "version": "1.4",
  "body": [
    {
      "type": "Container",
      "items": [
        {
          "type": "ColumnSet",
          "columns": [
            {
              "type": "Column",
              "width": "stretch",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "Title: ${if(title, title, 'N/A')}",
                  "wrap": true
                },
                {
                  "type": "TextBlock",
                  "text": "Description: ${if(description, description, 'N/A')}",
                  "wrap": true
                },
                {
                  "type": "TextBlock",
                  "text": "Assigned To: ${if(assignedTo, assignedTo, 'N/A')}",
                  "wrap": true
                },
                {
                  "type": "Image",
                  "url": "${image}",
                  "size": "Medium",
                  "$when": "${image != null}"
                }
              ]
            },
            {
              "type": "Column",
              "width": "auto",
              "items": [
                {
                  "type": "Image",
                  "url": "${if(image, image, '')}",
                  "size": "Medium"
                }
              ]
            }
          ]
        },
        {
          "type": "FactSet",
          "facts": [
            {
              "title": "Repair ID:",
              "value": "${if(id, id, 'N/A')}"
            },
            {
              "title": "Date:",
              "value": "${if(date, date, 'N/A')}"
            }
          ]
        }
      ]
    }
  ]
  },
  "previewCardTemplate": {
  "title": "Title: ${if(title, title, 'N/A')}",
  "subtitle": "Description: ${if(description, description, 'N/A')}",
  "text": "Assigned To: ${if(assignedTo, assignedTo, 'N/A')}",
  "image": {
    "url": "${image}",
    "$when": "${image != null}"
    }
  }
 }

Cartão de Pré-visualização

Um modelo de card de pré-visualização no esquema de modelo de composição de resposta é utilizado para mapear respostas JSON para uma pré-visualização card que os utilizadores veem quando selecionam um resultado de pesquisa. A pré-visualização card, em seguida, expande-se para um Cartão Ajustável na caixa de composição de mensagens. O modelo de card de pré-visualização faz parte do modelo de composição de resposta, que também inclui um modelo de Cartão Ajustável e metadados.

Captura de ecrã a mostrar um exemplo de extensão de composição que apresenta uma matriz de cartões de pré-visualização ao procurar uma palavra específica. Neste caso, procurar

Cartão Ajustável Expandido

Exemplo de como o Cartão Ajustável parece expandido quando um utilizador seleciona uma pré-visualização card. O Cartão Ajustável mostra os valores Título, Descrição completa, Atribuído A, RepairId e Data.

Parâmetros

Propriedade Tipo Descrição Obrigatório
version string A versão de esquema do modelo de composição de resposta atual. Sim
jsonPath string O caminho para a secção relevante nos resultados aos quais o responseCardTemplate e previewCardTemplate devem ser aplicados. Se não estiver definido, o objeto raiz é tratado como a secção relevante. Se a secção relevante for uma matriz, cada entrada é mapeada para responseCardTemplate e previewCardTemplate. Não
responseLayout responseLayoutType Especifica o esquema dos resultados na lista de opções da extensão de mensagem. Os tipos suportados são list e grid. Sim
responseCardTemplate adaptiveCardTemplate Um modelo para criar um Cartão Ajustável a partir de uma entrada de resultado. Sim
previewCardTemplate previewCardTemplate Um modelo para criar uma pré-visualização card a partir de uma entrada de resultados. O card de pré-visualização resultante é apresentado no menu de lista de opções da extensão de mensagem. Sim

Caminho Json

O caminho JSON é opcional, mas deve ser utilizado para matrizes ou onde o objeto a ser utilizado como dados para o Cartão Ajustável não é o objeto raiz. O caminho JSON deve seguir o formato definido pela Newtonsoft. Esta ferramenta pode ser utilizada. Pode utilizar a ferramenta JSON para validar se um caminho JSON está correto. Se o caminho JSON apontar para uma matriz, cada entrada nessa matriz está vinculada ao modelo Cartão Ajustável e devolve como resultados separados.

Exemplo Suponhamos que tem o seguinte JSON para uma lista de produtos e quer criar um resultado card para cada entrada.

{
   "version": "1.0",
   "title": "All Products",
   "warehouse": {
      "products": [
        ...
      ]
   }
}

Como pode ver, a matriz de resultados está em "produtos", que está aninhada em "armazém", pelo que o caminho JSON seria "warehouse.products".

Utilize https://adaptivecards.io/designer/ para pré-visualizar o Cartão Ajustável ao inserir o modelo no cartão Payload Editor e obter uma entrada de resposta de exemplo da sua matriz ou do seu objeto e inseri-lo no editor de Dados Idênticos à direita. Certifique-se de que o card é composto corretamente e é do seu agrado. O Teams suporta cartões até à versão 1.5, enquanto o estruturador suporta a versão 1.6.

Conversão de esquema OpenAPI

Observação

Enviamos um cabeçalho accept-language no pedido HTTP que é enviado para o ponto final definido no documento de descrição openAPI. A linguagem accept-language baseia-se na região do cliente do Teams e pode ser utilizada pelo programador para devolver uma resposta localizada.

Os seguintes tipos de dados no documento de descrição openAPI são convertidos em elementos dentro de um Cartão Ajustável da seguinte forma:

  • stringos tipos , number, integerboolean são convertidos num TextBlock.

    Exemplo
    • Esquema de Origem: string, , numberintegereboolean

       name:
         type: string
         example: doggie
      
    • Esquema de Destino: Textblock

      {
      "type": "TextBlock",
      "text": "name: ${if(name, name, 'N/A')}",
      "wrap": true
      }
      
  • array: uma matriz é convertida num contentor dentro do Cartão Ajustável.

    Exemplo
    • Esquema de origem: array

          type: array
                    items:
                    required:
                      - name
                    type: object
                      properties:
                      id:
                        type: integer
                      category:
                        type: object
                        properties:
                        name:
                          type: string
      
    • Esquema de Destino: Container

          {
                    "type": "Container",
                    "$data": "${$root}",
                    "items": [
                      {
                        "type": "TextBlock",
                        "text": "id: ${if(id, id, 'N/A')}",
                        "wrap": true
                      },
                      {
                        "type": "TextBlock",
                        "text": "category.name: ${if(category.name, category.name, 'N/A')}",
                        "wrap": true
                      }
                    ]
                  }
      
      
  • object: um objeto é convertido numa propriedade aninhada no Cartão Ajustável.

    Exemplo
    • Esquema de Origem: object

      components:
        schemas:
          Pet:
              category:
                type: object
              properties:
                id:
                  type: integer
                name:
                  type: string
      
      
    • Esquema de Destino: propriedade aninhada num Cartão Ajustável

      {
        "type": "TextBlock",
        "text": "category.id: ${if(category.id, category.id, 'N/A')}",
        "wrap": true
      },
      {
        "type": "TextBlock",
        "text": "category.name: ${if(category.name, category.name, 'N/A')}",
        "wrap": true
      }
      
      
  • image: se uma propriedade for um URL de imagem, é convertida num elemento Imagem no Cartão Ajustável.

    Exemplo
    • Esquema de origem: image

          image:
            type: string
            format: uri
            description: The URL of the image of the item to be repaired
      
      
    • Esquema de Destino: "Image"

      {
            "type": "Image",
            "url": "${image}",
            "$when": "${image != null}"
          }
      
      

Próxima etapa