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.
Observação
As extensões de mensagem baseadas em API dão suporte apenas a comandos de pesquisa.
As extensões de mensagem baseadas em API são um recurso do aplicativo Microsoft Teams que integra APIs externas diretamente ao Teams, aprimorando a usabilidade do aplicativo e oferecendo uma experiência de usuário perfeita. As extensões de mensagem baseadas em API oferecem suporte a comandos de pesquisa e podem ser usadas para buscar e exibir dados de serviços externos no Teams, simplificando os fluxos de trabalho ao reduzir a necessidade de alternar entre aplicativos.
Observação
Os agentes fornecem uma experiência mais flexível, inteligente e pronta para o futuro que permite um raciocínio mais avançado, um desenvolvimento mais simples e um melhor alinhamento com o Teams em evolução e a plataforma Microsoft 365. Recomendamos que você explore e crie agentes.
Para obter mais informações, confira Criar agentes declarativos e Criar agentes no Teams.
Se você tiver uma extensão de mensagem baseada em bot existente, também poderá estendê-la como um agente .
Antes de começar, verifique se você atende aos seguintes requisitos:
1. Descrição do OpenAPI (OAD)
Certifique-se de seguir as seguintes diretrizes para o documento Descrição do OpenAPI (OAD):
- As versões 2.0 e 3.0.x do OpenAPI são suportadas.
- JSON e YAML são os formatos com suporte.
- O corpo da solicitação, se presente, deve ser application/Json.
- Defina uma URL do servidor de protocolo HTTPS para a
servers.urlpropriedade. - Há suporte apenas para os métodos POST e GET HTTP.
- O documento de descrição do OpenAPI deve ter um
operationIdarquivo . - Somente um parâmetro necessário sem um valor padrão é permitido.
- Um parâmetro necessário com um valor padrão é considerado opcional.
- Os usuários não devem inserir um parâmetro para um cabeçalho ou cookie.
- A operação não deve ter um cabeçalho obrigatório ou parâmetros de cookie sem valores padrão.
- Certifique-se de que não haja referências remotas no documento Descrição do OpenAPI.
- Não há suporte para a construção de matrizes para a solicitação; no entanto, há suporte para objetos aninhados em um corpo de solicitação JSON.
- O Teams não dá suporte às
oneOfconstruções ,anyOf,allOf, enot(swagger.io).
O código a seguir é um exemplo de documento de descrição do OpenAPI:
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, consulte Estrutura do OpenAPI.
2. Manifesto do aplicativo
Certifique-se de seguir as seguintes diretrizes para o manifesto do aplicativo:
Defina a versão do manifesto do aplicativo como
1.17.Defina
composeExtensions.composeExtensionTypecomoapiBased.Defina
composeExtensions.apiSpecificationFilecomo o caminho relativo para o arquivo de descrição do OpenAPI dentro da pasta. Isso vincula o manifesto do aplicativo à especificação da API.Defina
apiResponseRenderingTemplateFilecomo o caminho relativo para o modelo de renderização de resposta. Isso especifica o local do modelo usado para renderizar respostas da API.Cada comando deve ter um link para o modelo de renderização de resposta. Isso conecta cada comando ao seu formato de resposta correspondente.
A
Commands.idpropriedade no manifesto do aplicativo deve corresponder à descrição dooperationIdOpenAPI.Se um parâmetro necessário não tiver um valor padrão, o comando
parameters.nameno manifesto do aplicativo deverá corresponder ao no documento Descrição doparameters.nameOpenAPI.Se não houver nenhum parâmetro obrigatório, o comando
parameters.nameno manifesto do aplicativo deverá corresponder ao opcionalparameters.namena Descrição do OpenAPI.Certifique-se de que os parâmetros de cada comando correspondam exatamente aos nomes dos parâmetros definidos para a operação na especificação OpenAPI.
Um modelo de renderização de resposta deve ser definido por comando, que é usado para converter respostas de uma API.
A descrição completa não deve exceder 128 caracteres.
{ "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.17/MicrosoftTeams.schema.json", + "manifestVersion": "1.17", "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": "9xxxxxxx-7xxx-4xxx-bxxx-1xxxxxxxxxxx" + } + }, + "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 à autorização para a extensão de mensagem baseada em API |
composeExtensions.authorization.authType |
Enumeração de possíveis tipos de autorização. Os valores com suporte são none, apiSecretServiceAuthe microsoftEntra. |
composeExtensions.authorization.apiSecretServiceAuthConfiguration |
Detalhes de captura de objeto necessários para fazer a autenticação de serviço. Aplicável somente quando o tipo de autenticação é apiSecretServiceAuth. |
composeExtensions.authorization.apiSecretServiceAuthConfiguration.apiSecretRegistrationId |
ID de registro retornada quando o desenvolvedor envia a chave de API por meio do Portal do desenvolvedor. |
composeExtensions.apiSpecificationFile |
Faz referência a um arquivo de Descrição do OpenAPI no pacote do aplicativo. Incluir quando o tipo é apiBased. |
composeExtensions.commands.id |
ID exclusiva que você atribui ao comando de pesquisa. A solicitação do usuário inclui essa ID. A ID deve corresponder ao OperationId disponível na descrição do OpenAPI. |
composeExtensions.commands.context |
Matriz em que os pontos de entrada para extensão de mensagem estão definidos. Os valores padrão são compose e commandBox. |
composeExtensions.commands.parameters |
Define uma lista estática de parâmetros para o comando. O nome deve ser mapeado para o na descrição do parameters.name OpenAPI. Se você estiver fazendo referência a uma propriedade no esquema do corpo da solicitação, o nome deverá ser mapeado para properties.name ou consultar parâmetros. |
composeExtensions.commands.apiResponseRenderingTemplateFile |
Modelo usado para formatar a resposta JSON da API do desenvolvedor para a resposta do Cartão Adaptável. [Obrigatório] |
Para obter mais informações, consulte composeExtensions.
3. Modelo de renderização de resposta
-
Defina a URL de referência de esquema na
$schemapropriedade para estabelecer a estrutura do seu modelo. -
Os valores com suporte para
responseLayoutsãolistegrid, que determinam como a resposta é apresentada visualmente. -
A
jsonPathé recomendado para matrizes ou quando os dados do Cartão Adaptável não são o objeto raiz. Por exemplo, se os dados estiverem aninhados emproductDetails, o caminho JSON seriaproductDetails. -
Defina
jsonPathcomo o caminho para os dados ou matrizes relevantes na resposta da API. Se o caminho apontar para uma matriz, cada entrada na matriz será associada ao modelo de Cartão Adaptável e retornará como um resultado separado. [Opcional] - Obtenha uma resposta de exemplo para validar o modelo de renderização de resposta. Isso serve como um teste para garantir que seu modelo funcione conforme o esperado.
- Use ferramentas como Fiddler ou Postman para chamar a API e garantir que a solicitação e a resposta sejam válidas. Esta etapa é crucial para solucionar problemas e confirmar se sua API está funcionando corretamente.
- Você pode usar o Adaptive Card Designer para vincular a resposta da API ao modelo de renderização de resposta e visualizar o Cartão Adaptável. Insira o modelo no EDITOR DE CONTEÚDO DO CARTÃO e insira a entrada de resposta de exemplo no EDITOR DE DADOS DE EXEMPLO.
O código a seguir é um exemplo de um modelo de renderização de resposta:
Exemplo de modelo de renderização de resposta
{
"version": "1.0",
"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 visualização
Cartão Adaptável Expandido
Parâmetros
| Propriedade | Tipo | Descrição | Obrigatório |
|---|---|---|---|
version |
string |
A versão do esquema do modelo de renderização de resposta atual. | Sim |
jsonPath |
string |
O caminho para a seção relevante nos resultados ao qual o responseCardTemplate e o previewCardTemplate devem ser aplicados. Se não for definido, o objeto raiz será tratado como a seção relevante. Se a seção relevante for uma matriz, cada entrada será mapeada para responseCardTemplate e previewCardTemplate. | Não |
responseLayout |
responseLayoutType |
Especifica o layout dos resultados no submenu da extensão de mensagem. Os tipos com suporte são list e grid. |
Sim |
responseCardTemplate |
adaptiveCardTemplate |
Um modelo para criar um Cartão Adaptável a partir de uma entrada de resultado. | Sim |
previewCardTemplate |
previewCardTemplate |
Um modelo para criar um card de visualização a partir de uma entrada de resultado. O card de visualização resultante é exibido no menu de submenu da extensão de mensagem. | Sim |
Caminho JSON
O caminho JSON é opcional, mas pode ser usado para matrizes ou quando o objeto a ser usado como dados para um Cartão Adaptável não é o objeto raiz. O caminho JSON deve seguir o formato definido pela Newtonsoft. Se o caminho JSON apontar para uma matriz, cada entrada nessa matriz será associada ao modelo de Cartão Adaptável e retornará como resultados separados.
Exemplo Digamos que você tenha o JSON abaixo para uma lista de produtos e queira criar um resultado de card para cada entrada.
{
"version": "1.0",
"title": "All Products",
"warehouse": {
"products": [
...
]
}
}
Como você pode ver, a matriz de resultados está em "produtos", que está aninhada em "warehouse", portanto, o caminho JSON seria "warehouse.products".
Use o Adaptive Card Designer para visualizar um Cartão Adaptável inserindo o modelo no Editor de Carga de Cartão. Pegue uma entrada de resposta de amostra de sua matriz ou para seu objeto e insira-a no Editor de Dados de Amostra. Certifique-se de que o card seja renderizado corretamente e seja do seu agrado.
Mapeamento de esquema
As propriedades no documento Descrição do OpenAPI são mapeadas para o modelo de Cartão Adaptável da seguinte maneira:
string,number,integerboolean, tipos são convertidos em um TextBlock.Exemplo
Esquema de origem:
string,number,integerebooleanname: type: string example: doggieEsquema de destino:
Textblock{ "type": "TextBlock", "text": "name: ${if(name, name, 'N/A')}", "wrap": true }
array: uma matriz é convertida em um contêiner dentro do Cartão Adaptável.Exemplo
Esquema de origem:
arraytype: array items: required: - name type: object properties: id: type: integer category: type: object properties: name: type: stringEsquema 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 em uma propriedade aninhada no Cartão Adaptável.Exemplo
Esquema de origem:
objectcomponents: schemas: Pet: category: type: object properties: id: type: integer name: type: stringEsquema de destino: propriedade aninhada em um Cartão Adaptá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 uma URL de imagem, ela será convertida em um elemento Image no Cartão Adaptável.Exemplo
Esquema de origem:
imageimage: type: string format: uri description: The URL of the image of the item to be repairedEsquema de destino:
"Image"{ "type": "Image", "url": "${image}", "$when": "${image != null}" }
Você pode criar uma extensão de mensagem baseada em API usando o Portal do desenvolvedor para Teams, o Microsoft 365 Agents Toolkit (anteriormente conhecido como Teams Toolkit) para Visual Studio Code, interface de linha de comando (CLI) ou Visual Studio.
- Portal do Desenvolvedor do Teams
- Visual Studio Code
- CLI do Kit de Ferramentas de Agentes do Microsoft 365
- Visual Studio
Para criar uma extensão de mensagem baseada em API usando o Portal do Desenvolvedor, siga estas etapas:
Acesse o portal do desenvolvedor.
Vá para Aplicativos.
Selecione + Novo aplicativo.
Insira um nome para o aplicativo e selecione a versão do manifesto como versão prévia do desenvolvedor público (devPreview).
Selecione Adicionar.
No painel esquerdo, em Configurar, atualize as seguintes Informações básicas:
- Nome completo
- Descrição curta
- Descrição longa
- Nome do desenvolvedor ou da empresa
- Site (deve ser uma URL HTTPS válida)
- Política de privacidade
- Termos de uso
Selecione Salvar.
Selecione Recursos do aplicativo.
Selecione a Extensão de mensagem.
Em Tipo de extensão de mensagem, selecione API.
- Se você receber um aviso de isenção de responsabilidade que diz que a extensão da mensagem do bot já está em uso pelos usuários. Deseja alterar o tipo de extensão de mensagem para API?, selecione Sim, alterar.
Em Especificação OpenAPI, selecione Carregar agora.
Selecione o documento de descrição da OpenAPI no formato JSON ou YAML e selecione Abrir.
Selecione Salvar. Um pop-up é exibido com a especificação de API da mensagem salva com sucesso.
Selecione Entendi.
Adicionar comandos
Observação
As extensões de mensagem criadas a partir de uma API dão suporte apenas a um único parâmetro.
Você pode adicionar comandos e parâmetros à sua extensão de mensagem para adicionar comandos:
Em Tipo de extensão de mensagem, selecione Adicionar.
Um pop-up Adicionar um comando é exibido com uma lista de todas as APIs disponíveis no documento Descrição do OpenAPI.
Selecione uma API na lista e selecione Avançar.
Em Modelo de resposta, selecione Carregar agora.
Observação
Se você tiver mais de uma API, certifique-se de carregar o modelo de resposta do Cartão Adaptável para cada API.
Selecione o arquivo de modelo de resposta do Cartão Adaptável no formato JSON e selecione Abrir.
Os seguintes atributos são atualizados automaticamente a partir do modelo de Cartão Adaptável:
- Tipo de Comando
- ID do comando
- Título do comando
- Nome do parâmetro
- Descrição do parâmetro
Em Detalhes, atualize a Descrição do comando.
Se você quiser iniciar um comando usando um gatilho no Microsoft 365 Copilot, ative a opção Executar este comando automaticamente quando um usuário abrir a alternância de extensão.
Selecione Adicionar. O comando é adicionado com êxito.
Selecione Salvar.
Em Autenticação e autorização, selecione qualquer uma das seguintes opções:
- Sem autenticação (não recomendado)
- Chave de API
- OAuth
Uma extensão de mensagem baseada em API é criada.
Para testar a extensão de mensagem baseada em API criada no Portal do Desenvolvedor, você pode usar os seguintes métodos:
Visualizar no Teams: abra sua extensão de mensagem e selecione Visualizar no Teams no canto superior direito. Você será redirecionado para o Teams, onde poderá adicionar o aplicativo ao Teams para visualizá-lo.
Baixar pacote do aplicativo: na página de extensão de mensagem, selecione Pacote do aplicativo no painel esquerdo e, em seguida, no canto superior esquerdo da janela, selecione Baixar pacote do aplicativo. O pacote do aplicativo é baixado em seu computador local em um arquivo .zip. Você pode carregar o pacote do aplicativo no Teams e testar a extensão de mensagem.
Vários parâmetros
Vários parâmetros permitem que extensões de mensagem baseadas em API tenham mais de um tipo de entrada para comandos de consulta. Por exemplo, você pode pesquisar animes por gênero, classificação, status e data.
Você pode especificar os tipos de entrada, títulos, descrições e campos obrigatórios para os parâmetros no manifesto.
- A
isRequiredpropriedade no campo parâmetro indica se um parâmetro é obrigatório para o comando de consulta. - A
namepropriedade doparameterscampo no manifesto do aplicativo deve corresponder aoidcampo no documento Descrição do OpenAPI para o parâmetro correspondente.
Exemplo
"composeExtensions": [
{
"composeExtensionType": "apiBased",
"apiSpecificationFile": "apiSpecificationFiles/openapi.json",
"commands": [
{
"context": [
"compose"
],
"type": "query",
"title": "Search Animes",
"id": "getAnimeSearch",
"parameters": [
{
"name": "q",
"title": "Search Query",
"description": "The search query",
"isRequired": true
},
{
"name": "type",
"inputType": "choiceset",
"title": "Type",
"description": "Available anime types",
"choices": [
{
"title": "TV",
"value": "tv"
},
{
"title": "OVA",
"value": "ova"
},
{
"title": "Movie",
"value": "movie"
},
{
"title": "Special",
"value": "special"
},
{
"title": "ONA",
"value": "ona"
},
{
"title": "Music",
"value": "music"
}
]
},
{
"name": "status",
"inputType": "choiceset",
"title": "Status",
"description": "Available airing statuses",
"choices": [
{
"title": "Airing",
"value": "airing"
},
{
"title": "Completed",
"value": "complete"
},
{
"title": "Upcoming",
"value": "upcoming"
}
]
},
{
"name": "rating",
"inputType": "choiceset",
"title": "Rating",
"description": "Available ratings",
"choices": [
{
"title": "G",
"value": "g"
},
{
"title": "PG",
"value": "pg"
},
{
"title": "PG-13",
"value": "pg13"
},
{
"title": "R",
"value": "r17"
},
{
"title": "R+",
"value": "r"
},
{
"title": "Rx",
"value": "rx"
}
]
}
],
"description": "Search animes",
"apiResponseRenderingTemplateFile": "response_json/getAnimeSearch.json"
},
{
"context": [
"compose"
],
"type": "query",
"title": "Search mangas",
"id": "getMangaSearch",
"parameters": [
{
"name": "q",
"title": "Search Query",
"description": "The search query",
"isRequired": true
},
{
"name": "type",
"inputType": "choiceset",
"title": "Type",
"description": "Available manga types",
"choices": [
{
"title": "Manga",
"value": "manga"
},
{
"title": "Novel",
"value": "novel"
},
{
"title": "Light Novel",
"value": "lightnovel"
},
{
"title": "One Shot",
"value": "oneshot"
},
{
"title": "Doujin",
"value": "doujin"
},
{
"title": "Manhwa",
"value": "manhwa"
},
{
"title": "Manhua",
"value": "manhua"
}
]
},
{
"name": "status",
"inputType": "choiceset",
"title": "Status",
"description": "Available manga statuses",
"choices": [
{
"title": "Publishing",
"value": "publishing"
},
{
"title": "Complete",
"value": "complete"
},
{
"title": "Hiatus",
"value": "hiatus"
},
{
"title": "Discontinued",
"value": "discontinued"
},
{
"title": "Upcoming",
"value": "upcoming"
}
]
},
{
"name": "start_date",
"title": "Start Date",
"description": "Start date of the manga",
"inputType": "date"
},
{
"name": "end_date",
"title": "End Date",
"description": "End date of the manga",
"inputType": "date"
}
],
Guias passo a passo
Para criar uma extensão de mensagem baseada em API, consulte criar uma extensão de mensagem baseada em API.