Creación de una extensión de mensaje basada en API

Nota:

Las extensiones de mensaje basadas en API solo admiten comandos de búsqueda.

Las extensiones de mensajes basadas en API son una funcionalidad de aplicación de Microsoft Teams que integra las API externas directamente en Teams, lo que mejora la facilidad de uso de la aplicación y ofrece una experiencia de usuario sin problemas. Las extensiones de mensajes basadas en API admiten comandos de búsqueda y se pueden usar para capturar y mostrar datos de servicios externos dentro de Teams, lo que simplifica los flujos de trabajo al reducir la necesidad de cambiar entre aplicaciones.

Antes de empezar, asegúrese de cumplir los siguientes requisitos:


1. Descripción de OpenAPI (OAD)

Asegúrese de cumplir las siguientes directrices para el documento de descripción de OpenAPI (OAD):

  • Se admiten las versiones 2.0 y 3.0.x de OpenAPI.
  • JSON y YAML son los formatos admitidos.
  • El cuerpo de la solicitud, si está presente, debe ser application/Json.
  • Defina una dirección URL del servidor de protocolo HTTPS para la servers.url propiedad .
  • Solo se admiten los métodos HTTP POST y GET.
  • El documento Descripción de OpenAPI debe tener un .operationId
  • Solo se permite un parámetro necesario sin un valor predeterminado.
  • Un parámetro obligatorio con un valor predeterminado se considera opcional.
  • Los usuarios no deben especificar un parámetro para un encabezado o cookie.
  • La operación no debe tener un encabezado o parámetros de cookie necesarios sin valores predeterminados.
  • Asegúrese de que no haya referencias remotas en el documento Descripción de OpenAPI.
  • No se admite la construcción de matrices para la solicitud; sin embargo, se admiten objetos anidados dentro de un cuerpo de solicitud JSON.
  • Teams no admite las oneOfconstrucciones , anyOf, allOfy not (swagger.io).

El código siguiente es un ejemplo de un documento de descripción de 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 obtener más información, consulte Estructura de OpenAPI.


2. Manifiesto de aplicación

Asegúrese de cumplir las siguientes directrices para el manifiesto de la aplicación:

  • Establezca la versión del manifiesto de la aplicación en 1.17.

  • Establezca en composeExtensions.composeExtensionTypeapiBased.

  • Defina composeExtensions.apiSpecificationFile como la ruta de acceso relativa al archivo de descripción de OpenAPI dentro de la carpeta. Esto vincula el manifiesto de aplicación a la especificación de API.

  • Defina apiResponseRenderingTemplateFile como la ruta de acceso relativa a la plantilla de representación de respuesta. Esto especifica la ubicación de la plantilla que se usa para representar las respuestas de la API.

  • Cada comando debe tener un vínculo a la plantilla de representación de respuesta. Esto conecta cada comando a su formato de respuesta correspondiente.

  • La Commands.id propiedad del manifiesto de la aplicación debe coincidir con en operationId la descripción de OpenAPI.

  • Si un parámetro necesario no tiene un valor predeterminado, el comando parameters.name del manifiesto de la aplicación debe coincidir con el parameters.name del documento Descripción de OpenAPI.

  • Si no hay ningún parámetro necesario, el comando parameters.name del manifiesto de la aplicación debe coincidir con el opcional parameters.name en la descripción de OpenAPI.

  • Asegúrese de que los parámetros de cada comando coinciden exactamente con los nombres de los parámetros definidos para la operación en la especificación de OpenAPI.

  • Se debe definir una plantilla de representación de respuesta por comando, que se usa para convertir respuestas desde una API.

  • La descripción completa no debe superar los 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": []
    }
    

Parameters

Nombre Descripción
composeExtensions.composeExtensionType Compose tipo de extensión. Actualice el valor a apiBased.
composeExtensions.authorization Información relacionada con la autorización para la extensión de mensaje basada en API
composeExtensions.authorization.authType Enumeración de posibles tipos de autorización. Los valores admitidos son none, apiSecretServiceAuthy microsoftEntra.
composeExtensions.authorization.apiSecretServiceAuthConfiguration Detalles de captura de objetos necesarios para realizar la autenticación del servicio. Solo se aplica cuando el tipo de autenticación es apiSecretServiceAuth.
composeExtensions.authorization.apiSecretServiceAuthConfiguration.apiSecretRegistrationId Id. de registro devuelto cuando el desarrollador envía la clave de API a través del Portal para desarrolladores.
composeExtensions.apiSpecificationFile Hace referencia a un archivo de descripción de OpenAPI en el paquete de la aplicación. Incluya cuando el tipo es apiBased.
composeExtensions.commands.id Identificador único que se asigna al comando de búsqueda. La solicitud de usuario incluye este id. El identificador debe coincidir con el OperationId disponible en la descripción de OpenAPI.
composeExtensions.commands.context Matriz donde se definen los puntos de entrada de la extensión de mensaje. Los valores predeterminados son compose y commandBox.
composeExtensions.commands.parameters Define una lista estática de parámetros para el comando. El nombre debe asignarse a en parameters.name la descripción de OpenAPI. Si hace referencia a una propiedad en el esquema del cuerpo de la solicitud, el nombre debe asignarse a properties.name los parámetros de consulta o .
composeExtensions.commands.apiResponseRenderingTemplateFile Plantilla usada para dar formato a la respuesta JSON de la API del desarrollador a la respuesta de tarjeta adaptable. [Obligatorio]

Para obtener más información, vea composeExtensions.


3. Plantilla de representación de respuesta

Nota:

Teams admite tarjetas adaptables hasta la versión 1.5 y las tarjetas adaptables Designer admiten hasta la versión 1.6.

  • Defina la dirección URL de referencia del esquema en la $schema propiedad para establecer la estructura de la plantilla.
  • Los valores admitidos para responseLayout son list y grid, que determinan cómo se presenta visualmente la respuesta.
  • Se recomienda para jsonPath matrices o cuando los datos de la tarjeta adaptable no son el objeto raíz. Por ejemplo, si los datos están anidados en productDetails, la ruta de acceso JSON sería productDetails.
  • Defina jsonPath como la ruta de acceso a los datos o matriz pertinentes en la respuesta de la API. Si la ruta de acceso apunta a una matriz, cada entrada de la matriz se enlaza con la plantilla tarjeta adaptable y devuelve como resultado independiente. [Opcional]
  • Obtenga una respuesta de ejemplo para validar la plantilla de representación de respuesta. Esto sirve como prueba para asegurarse de que la plantilla funciona según lo esperado.
  • Use herramientas como Fiddler o Postman para llamar a la API y asegurarse de que la solicitud y la respuesta son válidas. Este paso es fundamental para solucionar problemas y confirmar que la API funciona correctamente.
  • Puede usar la tarjeta adaptable Designer para enlazar la respuesta de la API a la plantilla de representación de respuesta y obtener una vista previa de la tarjeta adaptable. Inserte la plantilla en el EDITOR DE CARGA ÚTIL DE TARJETA e inserte la entrada de respuesta de ejemplo en EL EDITOR DE DATOS DE EJEMPLO.

El código siguiente es un ejemplo de una plantilla de representación de respuesta:

Ejemplo de plantilla de representación de respuesta
{
"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}"
    }
  }
 }

Tarjeta de vista previa

Captura de pantalla que muestra un ejemplo de extensión de redacción que muestra una matriz de tarjetas de vista previa al buscar una palabra específica. En este caso, la búsqueda de

Tarjeta adaptable expandida

Ejemplo de cómo se ve la tarjeta adaptable expandida una vez que un usuario selecciona una tarjeta de vista previa. La tarjeta adaptable muestra los valores Título, Descripción completa, AssignedTo, RepairId y Fecha.

Parameters

Propiedad Tipo Descripción Obligatorio
version string Versión del esquema de la plantilla de representación de respuesta actual. Yes
jsonPath string Ruta de acceso a la sección pertinente en los resultados a los que se deben aplicar responseCardTemplate y previewCardTemplate. Si no se establece, el objeto raíz se trata como la sección pertinente. Si la sección pertinente es una matriz, cada entrada se asigna a responseCardTemplate y previewCardTemplate. No
responseLayout responseLayoutType Especifica el diseño de los resultados en el control flotante de la extensión de mensaje. Los tipos admitidos son list y grid. Yes
responseCardTemplate adaptiveCardTemplate Plantilla para crear una tarjeta adaptable a partir de una entrada de resultado. Yes
previewCardTemplate previewCardTemplate Plantilla para crear una tarjeta de vista previa a partir de una entrada de resultado. La tarjeta de vista previa resultante se muestra en el menú desplegable extensión de mensaje. Yes

Ruta de acceso json

La ruta de acceso JSON es opcional, pero debe usarse para matrices o donde el objeto que se va a usar como datos de la tarjeta adaptable no es el objeto raíz. La ruta de acceso JSON debe seguir el formato definido por Newtonsoft. Si la ruta de acceso JSON apunta a una matriz, cada entrada de esa matriz se enlaza con la plantilla de tarjeta adaptable y devuelve como resultados independientes.

Ejemplo Supongamos que tiene el código JSON siguiente para una lista de productos y desea crear un resultado de tarjeta para cada entrada.

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

Como puede ver, la matriz de resultados está en "products", que está anidada en "warehouse", por lo que la ruta de acceso JSON sería "warehouse.products".

Use https://adaptivecards.io/designer/ para obtener una vista previa de la tarjeta adaptable insertando la plantilla en la carga útil de la tarjeta Editor, tome una entrada de respuesta de ejemplo de la matriz o del objeto e insértelo en el editor De los mismos datos de la derecha. Asegúrese de que la tarjeta se representa correctamente y es a su gusto. Tenga en cuenta que Teams admite tarjetas hasta la versión 1.5, mientras que el diseñador admite la versión 1.6.

Asignación de esquemas

Las propiedades del documento Descripción de OpenAPI se asignan a la plantilla tarjeta adaptable como se indica a continuación:

  • string, number, integer, boolean los tipos se convierten en textblock.

    Ejemplo
    • Esquema de origen: string, number, integery boolean

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

      {
      "type": "TextBlock",
      "text": "name: ${if(name, name, 'N/A')}",
      "wrap": true
      }
      
  • array: una matriz se convierte en un contenedor dentro de la tarjeta adaptable.

    Ejemplo
    • Esquema de origen: 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: un objeto se convierte en una propiedad anidada en la tarjeta adaptable.

    Ejemplo
    • Esquema de origen: object

      components:
        schemas:
          Pet:
              category:
                type: object
              properties:
                id:
                  type: integer
                name:
                  type: string
      
      
    • Esquema de destino: propiedad anidada en una tarjeta adaptable

      {
        "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: si una propiedad es una dirección URL de imagen, se convierte en un elemento Image de la tarjeta adaptable.

    Ejemplo
    • Esquema de origen: 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}"
          }
      
      

Puede crear una extensión de mensaje basada en API mediante el Portal para desarrolladores para Teams y teams Toolkit para Visual Studio Code, la interfaz de línea de comandos (CLI) o Visual Studio.

Para crear una extensión de mensaje basada en API mediante el Portal para desarrolladores para Teams, siga estos pasos:

  1. Vaya al Portal para desarrolladores de Teams.

  2. Vaya a Aplicaciones.

  3. Seleccione + Nuevas aplicaciones.

  4. Escriba un nombre de la aplicación y seleccione la versión del manifiesto como Versión preliminar del desarrollador público (devPreview).

  5. Seleccione Agregar.

    Captura de pantalla que muestra el nombre de la aplicación y la versión del manifiesto seleccionadas como versión preliminar más reciente (devPreview) en el Portal para desarrolladores.

  6. En el panel izquierdo, en Configurar, actualice la siguiente información básica:

    1. Nombre completo
    2. Descripción breve
    3. Descripción larga
    4. Nombre del desarrollador o de la empresa
    5. Sitio web (debe ser una dirección URL HTTPS válida)
    6. Directiva de privacidad
    7. Términos de uso
  7. Haga clic en Guardar.

  8. Seleccione Características de la aplicación.

  9. Seleccione Extensión de mensajería.

    Captura de pantalla que muestra la opción de extensión de mensaje en el Portal para desarrolladores de Teams.

  10. En Tipo de extensión de mensaje, seleccione API.

    1. Si recibe una declinación de responsabilidades, que lee La extensión de mensaje del bot ya está en uso por parte de los usuarios. ¿Desea cambiar el tipo de extensión de mensaje a API?. Seleccione Sí, cambie.
  11. En Especificación de OpenAPI, seleccione Cargar ahora.

    Captura de pantalla que muestra la opción Cargar ahora en el Portal para desarrolladores de Teams.

  12. Seleccione el documento Descripción de OpenAPI en formato JSON o YAML y seleccione Abrir.

  13. Haga clic en Guardar. Aparece un elemento emergente con la especificación de API de mensaje guardada correctamente.

  14. Seleccione Got it (Lo tengo).

    Captura de pantalla que muestra un ejemplo de la especificación de API guardada correctamente y el botón Obtenerlo.

Agregar comandos

Nota:

Las extensiones de mensaje creadas a partir de una API solo admiten un único parámetro.

Puede agregar comandos y parámetros a la extensión de mensaje para agregar comandos:

  1. En Tipo de extensión de mensaje, seleccione Agregar.

    Captura de pantalla que muestra la opción agregar para agregar comandos en el Portal para desarrolladores de Teams.

    Aparece un elemento emergente Agregar comando con una lista de todas las API disponibles en el documento Descripción de OpenAPI.

  2. Seleccione una API en la lista y seleccione Siguiente.

    Captura de pantalla que muestra la lista de API del documento de descripción de OpenAPI en la ventana emergente Agregar un comando.

    Aparece un elemento Command details (Detalles del comando ).

  3. En Detalles del comando, vaya a Plantilla de tarjeta adaptable y seleccione Cargar ahora.

    Captura de pantalla que muestra la opción Cargar ahora para agregar la plantilla tarjeta adaptable en para el comando.

    Nota:

    Si tiene más de una API, asegúrese de cargar la plantilla de tarjeta adaptable para cada API.

  4. Seleccione el archivo de plantilla tarjeta adaptable en formato JSON y seleccione Abrir.

    Los siguientes atributos se actualizan automáticamente desde la plantilla tarjeta adaptable:

    • Tipo de comando
    • Identificador de comando
    • Título del comando
    • Nombre del parámetro
    • Descripción del parámetro

    Captura de pantalla que muestra los campos disponibles en la página de detalles del comando.

  5. En Detalles, actualice la descripción del comando.

    1. Si desea iniciar un comando con un desencadenador en Microsoft 365 Copilot, active ejecutar automáticamente el comando cuando un usuario abra el botón de alternancia de extensión.
  6. Seleccione Agregar. El comando se agrega correctamente.

  7. Haga clic en Guardar.

  8. En Autenticación, seleccione cualquiera de las opciones siguientes:

    • Sin autenticación
    • Clave de API

Se crea una extensión de mensaje basada en API.

Captura de pantalla que muestra el complemento para Microsoft 365 Copilot creado en la página de características de la aplicación en el Portal para desarrolladores de Teams.

Para probar la extensión de mensaje basada en API creada en el Portal para desarrolladores de Teams, puede usar los métodos siguientes:

  • Versión preliminar en Teams: en el Portal para desarrolladores, abra la extensión de mensaje y seleccione Vista previa en Teams en la esquina superior derecha. Se le redirigirá a Teams, donde puede agregar la aplicación a Teams para obtener una vista previa de la aplicación.

  • Descargar paquete de aplicación: en la página de extensión del mensaje, seleccione Paquete de aplicación en el panel izquierdo y, a continuación, en la esquina superior izquierda de la ventana, seleccione Descargar paquete de aplicación. El paquete de la aplicación se descarga en la máquina local en un archivo .zip. Puede cargar el paquete de la aplicación en los equipos y probar la extensión del mensaje.

Guías paso a paso

Para compilar una extensión de mensaje basada en API, siga estas guías paso a paso:

Vea también

Autenticación para extensiones de mensajes basadas en API