Упражнение. Создание декларативного агента с подключаемым модулем API

Завершено

Расширение декларативного агента с помощью действий позволяет ему получать и обновлять данные, хранящиеся во внешних системах, в режиме реального времени. С помощью подключаемых модулей API можно подключаться к внешним системам с помощью API для получения и обновления информации.

Скачивание начального проекта

Начните с скачивания примера проекта. В веб-браузере:

  1. Перейдите по адресу https://github.com/microsoft/learn-declarative-agent-api-plugin-typescript.
  2. Если у вас есть учетная запись GitHub:
    1. Выберите раскрывающийся список Использовать этот шаблон и в меню выберите Создать репозиторий.

      Снимок экрана: параметр создания репозитория на сайте GitHub.

    2. В списке доступных владельцев выберите свою учетную запись.

    3. Присвойте репозиторию имя da-ristorante-api.

    4. Подтвердите создание репозитория с помощью кнопки Создать репозиторий .

    5. Подождите, пока GitHub создаст репозиторий. Затем скопируйте URL-адрес репозитория.

      Снимок экрана: параметр на сайте GitHub для копирования URL-адреса репозитория.

    6. Откройте командную строку.

    7. В командной строке измените рабочий каталог на место, в котором вы хотите сохранить проект на диске.

    8. Клонируйте репозиторий с помощью следующей команды: git clone https://github.com/your-user/your-repo.

    9. Откройте клонированную папку в Visual Studio Code.

  3. Если у вас нет учетной записи GitHub:
    1. Скачайте содержимое репозитория в виде ZIP-файла.

      Снимок экрана: параметр на сайте GitHub для скачивания репозитория в виде ZIP-файла.

    2. Извлеките содержимое ZIP-файла на диске.

    3. Откройте папку в Visual Studio Code.

Пример проекта представляет собой проект Microsoft 365 Agents Toolkit, включающий декларативный агент и анонимный API, работающий на Функции Azure. Декларативный агент идентичен только что созданному декларативному агенту с помощью microsoft 365 Agents Toolkit. API принадлежит вымышленному итальянскому ресторану и позволяет просматривать сегодняшнее меню и размещать заказы.

Изучение определения API

Сначала ознакомьтесь с определением API для API итальянского ресторана.

В Visual Studio Code:

  1. В представлении Обозреватель откройте файл appPackage/apiSpecificationFile/ristorante.yml. Файл представляет собой спецификацию OpenAPI, которая описывает API итальянского ресторана.

  2. Найдите свойство servers.url

    servers:
      - url: http://localhost:7071/api
        description: Il Ristorante API server
    

    Обратите внимание, что он указывает на локальный URL-адрес, соответствующий стандартному URL-адресу при локальном запуске Функции Azure.

  3. Найдите свойство paths , которое содержит две операции: /dishes для получения текущего меню и /orders для размещения заказа.

    Важно!

    Обратите внимание, что каждая операция содержит свойство operationId , которое однозначно идентифицирует операцию в спецификации API. Copilot требует, чтобы у каждой операции был уникальный идентификатор, чтобы он знал, какой API следует вызывать для конкретных запросов пользователей.

Изучение реализации API

Далее просмотрите пример API, который вы используете в этом упражнении.

В Visual Studio Code:

  1. В представлении Обозреватель откройте файл src/data.json. Файл содержит вымышленный пункт меню для нашего итальянского ресторана. Каждое блюдо состоит из:

    • имя
    • описание
    • ссылка на изображение,
    • цена
    • в каком курсе он подается,
    • тип (блюдо или напиток),
    • при необходимости список аллергенов

    В этом упражнении API используют этот файл в качестве источника данных.

  2. Затем разверните папку src/functions . Обратите внимание на два файла с именами dishes.ts и placeOrder.ts. Эти файлы содержат реализацию двух операций, определенных в спецификации API.

  3. Откройте файл src/functions/dishes.ts . Уделите некоторое время, чтобы узнать, как работает API. Он начинается с загрузки примера данных из файла src/functions/data.json .

    import data from "../data.json";
    

    Затем он ищет в различных параметрах строки запроса возможные фильтры, которые может пройти клиент, вызывающий API.

    const course = req.query.get('course');
    const allergensString = req.query.get('allergens');
    const allergens: string[] = allergensString ? allergensString.split(",") : [];
    const type = req.query.get('type');
    const name = req.query.get('name');
    

    На основе фильтров, указанных в запросе, API фильтрует набор данных и возвращает ответ.

  4. Затем изучите API для размещения заказов, определенных в файле src/functions/placeOrder.ts . API начинается с ссылки на пример данных. Затем он определяет форму заказа, отправляемого клиентом в тексте запроса.

    interface OrderedDish {
      name?: string;
      quantity?: number;
    }
    
    interface Order {
      dishes: OrderedDish[];
    }
    

    Когда API обрабатывает запрос, он сначала проверяет, содержит ли запрос текст и имеет ли он правильную форму. В противном случае запрос отклоняется с ошибкой 400 Bad Request.

    let order: Order | undefined;
    try {
      order = await req.json() as Order | undefined;
    }
    catch (error) {
      return {
        status: 400,
        jsonBody: { message: "Invalid JSON format" },
      } as HttpResponseInit;
    }
    
    if (!order.dishes || !Array.isArray(order.dishes)) {
      return {
        status: 400,
        jsonBody: { message: "Invalid order format" }
      } as HttpResponseInit;
    }
    

    Затем API разрешает запрос в блюда в меню и вычисляет общую цену.

    let totalPrice = 0;
    const orderDetails = order.dishes.map(orderedDish => {
      const dish = data.find(d => d.name.toLowerCase().includes(orderedDish.name.toLowerCase()));
      if (dish) {
        totalPrice += dish.price * orderedDish.quantity;
        return {
          name: dish.name,
          quantity: orderedDish.quantity,
          price: dish.price,
        };
      }
      else {
        context.error(`Invalid dish: ${orderedDish.name}`);
        return null;
      }
    });
    

    Важно!

    Обратите внимание, что API ожидает, что клиент укажет блюдо частью его имени, а не идентификатором. Это связано с тем, что большие языковые модели лучше работают со словами, чем числами. Кроме того, перед вызовом API для размещения заказа Copilot имеет имя блюда, которое легко доступно в рамках запроса пользователя. Если copilot должен был ссылаться на блюдо по его идентификатору, ему сначала нужно будет получить, который требует дополнительных запросов API, и что Copilot не может сделать сейчас.

    Когда API будет готов, он возвращает ответ с общей ценой, идентификатором заказа и состоянием.

    const orderId = Math.floor(Math.random() * 10000);
    
    return {
      status: 201,
      jsonBody: {
        order_id: orderId,
        status: "confirmed",
        total_price: totalPrice,
      }
    } as HttpResponseInit;
    

Создание определения подключаемого модуля

Следующим шагом является добавление определения подключаемого модуля в проект. Определение подключаемого модуля содержит следующие сведения:

  • Какие действия может выполнять подключаемый модуль.
  • Какова форма ожидаемых и возвращаемых данных.
  • Как декларативный агент должен вызывать базовый API.

Добавление базовой структуры определения подключаемого модуля

В Visual Studio Code:

  1. В папку appPackage добавьте новый файл с именем ai-plugin.json.

  2. Вставьте следующее содержимое:

    {
      "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.1/schema.json",
      "schema_version": "v2.1",
      "namespace": "ilristorante",
      "name_for_human": "Il Ristorante",
      "description_for_human": "See the today's menu and place orders",
      "description_for_model": "Plugin for getting the today's menu, optionally filtered by course and allergens, and placing orders",
      "functions": [ 
      ],
      "runtimes": [
      ],
      "capabilities": {
        "localization": {},
        "conversation_starters": []
      }
    }
    

    Файл содержит базовую структуру для подключаемого модуля API с описанием человека и модели. В description_for_model содержатся подробные сведения о том, что может сделать подключаемый модуль, чтобы помочь агенту понять, когда он должен рассмотреть возможность его вызова.

  3. Сохраните изменения.

Определение функций

Подключаемый модуль API определяет одну или несколько функций, которые сопоставляют с операциями API, определенными в спецификации API. Каждая функция состоит из имени и описания, а также определения ответа, которое указывает агенту, как отображать данные для пользователей.

Определение функции для получения меню

Начните с определения функции для получения сведений о сегодняшнем меню.

В Visual Studio Code:

  1. Откройте файл appPackage/ai-plugin.json .

  2. В массиве функций добавьте следующий фрагмент кода:

    {
      "name": "getDishes",
      "description": "Returns information about the dishes on the menu. Can filter by course (breakfast, lunch or dinner), name, allergens, or type (dish, drink).",
      "capabilities": {
        "response_semantics": {
          "data_path": "$.dishes",
          "properties": {
            "title": "$.name",
            "subtitle": "$.description"
          }
        }
      }
    }
    

    Сначала определите функцию, которая вызывает операцию getDishes из спецификации API. Затем укажите описание функции. Это описание важно, так как Copilot использует его, чтобы решить, какую функцию следует вызывать для запроса пользователя.

    В свойстве response_semantics укажите, как Copilot должен отображать данные, полученные от API. Так как API возвращает сведения о блюдах в меню в свойстве "блюда", для свойства $.dishesdata_path задается выражение JSONPath.

    Затем в разделе свойств вы сопоставляете свойства из ответа API, представляющие заголовок, описание и URL-адрес. Так как в этом случае у блюд нет URL-адреса, вы только сопоставляете название и описание.

  3. Полный фрагмент кода выглядит следующим образом:

    {
      "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.1/schema.json",
      "schema_version": "v2.1",
      "namespace": "ilristorante",
      "name_for_human": "Il Ristorante",
      "description_for_human": "See the today's menu and place orders",
      "description_for_model": "Plugin for getting the today's menu, optionally filtered by course and allergens, and placing orders",
      "functions": [
        {
          "name": "getDishes",
          "description": "Returns information about the dishes on the menu. Can filter by course (breakfast, lunch or dinner), name, allergens, or type (dish, drink).",
          "capabilities": {
            "response_semantics": {
              "data_path": "$.dishes",
              "properties": {
                "title": "$.name",
                "subtitle": "$.description"
              }
            }
          }
        }
      ],
      "runtimes": [
      ],
      "capabilities": {
        "localization": {},
        "conversation_starters": []
      }
    }
    
  4. Сохраните изменения.

Определение функции для размещения заказа

Затем определите функцию для размещения заказа.

В Visual Studio Code:

  1. Откройте файл appPackage/ai-plugin.json .

  2. В конец массива функций добавьте следующий фрагмент кода:

    {
      "name": "placeOrder",
      "description": "Places an order and returns the order details",
      "capabilities": {
        "response_semantics": {
          "data_path": "$",
          "properties": {
            "title": "$.order_id",
            "subtitle": "$.total_price"
          }
        }
      }
    }
    

    Сначала вы ссылаетесь на операцию API с id placeOrder. Затем укажите описание, которое Copilot использует для сопоставления этой функции с запросом пользователя. Затем вы укажи Copilot, как вернуть данные. Ниже приведены данные, которые API возвращает после размещения заказа:

    {
      "order_id": 6532,
      "status": "confirmed",
      "total_price": 21.97
    }
    

    Так как данные, которые необходимо отобразить, находятся непосредственно в корне объекта ответа, необходимо задать data_path$, указывающее верхний узел объекта JSON. Заголовок определяется для отображения номера заказа и подзаголовка его цены.

  3. Полный файл выглядит следующим образом:

    {
      "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.1/schema.json",
      "schema_version": "v2.1",
      "namespace": "ilristorante",
      "name_for_human": "Il Ristorante",
      "description_for_human": "See the today's menu and place orders",
      "description_for_model": "Plugin for getting the today's menu, optionally filtered by course and allergens, and placing orders",
      "functions": [
        {
          "name": "getDishes",
          "description": "Returns information about the dishes on the menu. Can filter by course (breakfast, lunch or dinner), name, allergens, or type (dish, drink).",
          ...trimmed for brevity
        },
        {
          "name": "placeOrder",
          "description": "Places an order and returns the order details",
          "capabilities": {
            "response_semantics": {
              "data_path": "$",
              "properties": {
                "title": "$.order_id",
                "subtitle": "$.total_price"
              }
            }
          }
        }
      ],
      "runtimes": [
      ],
      "capabilities": {
        "localization": {},
        "conversation_starters": []
      }
    }
    
  4. Сохраните изменения.

Определение сред выполнения

После определения функций для вызова Copilot следующим шагом является указание способа их вызова. Это можно сделать в разделе среды выполнения определения подключаемого модуля.

В Visual Studio Code:

  1. Откройте файл appPackage/ai-plugin.json .

  2. В массиве сред выполнения добавьте следующий код:

    {
      "type": "OpenApi",
      "auth": {
        "type": "None"
      },
      "spec": {
        "url": "apiSpecificationFile/ristorante.yml"
      },
      "run_for_functions": [
        "getDishes",
        "placeOrder"
      ]
    }
    

    Сначала вы указываете Copilot, что вы предоставляете ему информацию OpenAPI о вызове API (тип OpenApi) и что он является анонимным (auth.type: None). Затем в разделе спецификации укажите относительный путь к спецификации API, расположенной в проекте. Наконец, в свойстве run_for_functions перечислены все функции, принадлежащие этому API.

  3. Полный файл выглядит следующим образом:

    {
      "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.1/schema.json",
      "schema_version": "v2.1",
      "namespace": "ilristorante",
      "name_for_human": "Il Ristorante",
      "description_for_human": "See the today's menu and place orders",
      "description_for_model": "Plugin for getting the today's menu, optionally filtered by course and allergens, and placing orders",
      "functions": [
        {
          "name": "getDishes",
          ...trimmed for brevity
        },
        {
          "name": "placeOrder",
          ...trimmed for brevity
        }
      ],
      "runtimes": [
        {
          "type": "OpenApi",
          "auth": {
            "type": "None"
          },
          "spec": {
            "url": "apiSpecificationFile/ristorante.yml"
          },
          "run_for_functions": [
            "getDishes",
            "placeOrder"
          ]
        }
      ],
      "capabilities": {
        "localization": {},
        "conversation_starters": []
      }
    }
    
  4. Сохраните изменения.

Подключение определения подключаемого модуля к декларативному агенту

После завершения создания определения подключаемого модуля API его необходимо зарегистрировать в декларативном агенте. Когда пользователи взаимодействуют с декларативным агентом, он сопоставляет запрос пользователя с определенными подключаемыми модулями API и вызывает соответствующие функции.

В Visual Studio Code:

  1. Откройте файл appPackage/declarativeAgent.json .

  2. После свойства instructions добавьте следующий фрагмент кода:

    "actions": [
      {
        "id": "menuPlugin",
        "file": "ai-plugin.json"
      }
    ]
    

    С помощью этого фрагмента вы подключаете декларативный агент к подключаемого модуля API. Вы указываете уникальный идентификатор подключаемого модуля и указываете агенту, где он может найти определение подключаемого модуля.

  3. Полный файл выглядит следующим образом:

    {
      "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.0/schema.json",
      "version": "v1.0",
      "name": "Declarative agent",
      "description": "Declarative agent created with Microsoft 365 Agents Toolkit",
      "instructions": "$[file('instruction.txt')]",
      "actions": [
        {
          "id": "menuPlugin",
          "file": "ai-plugin.json"
        }
      ]
    }
    
  4. Сохраните изменения.

Обновление сведений и инструкций по декларативному агенту

Декларативный агент, который вы создаете в этом упражнении, помогает пользователям просматривать меню местного итальянского ресторана и размещать заказы. Чтобы оптимизировать агент для этого сценария, обновите его имя, описание и инструкции.

В Visual Studio Code:

  1. Обновите сведения о декларативном агенте:
    1. Откройте файл appPackage/declarativeAgent.json .
    2. Обновите значение свойства name на Il Ristorante.
    3. Обновите значение свойства описания , чтобы заказать самые вкусные итальянские блюда и напитки, не выходя из вашего стола.
    4. Сохраните изменения.
  2. Инструкции по обновлению декларативного агента:
    1. Откройте файл appPackage/instruction.txt .

    2. Замените его содержимое следующим:

      You are an assistant specialized in helping users explore the menu of an Italian restaurant and place orders. You interact with the restaurant's menu API and guide users through the ordering process, ensuring a smooth and delightful experience. Follow the steps below to assist users in selecting their desired dishes and completing their orders:
      
      ### General Behavior:
      - Always greet the user warmly and offer assistance in exploring the menu or placing an order.
      - Use clear, concise language with a friendly tone that aligns with the atmosphere of a high-quality local Italian restaurant.
      - If the user is browsing the menu, offer suggestions based on the course they are interested in (breakfast, lunch, or dinner).
      - Ensure the conversation remains focused on helping the user find the information they need and completing the order.
      - Be proactive but never pushy. Offer suggestions and be informative, especially if the user seems uncertain.
      
      ### Menu Exploration:
      - When a user requests to see the menu, use the `GET /dishes` API to retrieve the list of available dishes, optionally filtered by course (breakfast, lunch, or dinner).
        - Example: If a user asks for breakfast options, use the `GET /dishes?course=breakfast` to return only breakfast dishes.
      - Present the dishes to the user with the following details:
        - Name of the dish
        - A tasty description of the dish
        - Price in € (Euro) formatted as a decimal number with two decimal places
        - Allergen information (if relevant)
        - Don't include the URL.
      
      ### Beverage Suggestion:
      - If the order does not already include a beverage, suggest a suitable beverage option based on the course.
      - Use the `GET /dishes?course={course}&type=drink` API to retrieve available drinks for that course.
      - Politely offer the suggestion: *"Would you like to add a beverage to your order? I recommend [beverage] for [course]."*
      
      ### Placing the Order:
      - Once the user has finalized their order, use the `POST /order` API to submit the order.
        - Ensure the request includes the correct dish names and quantities as per the user's selection.
        - Example API payload:
      
          ```json
          {
            "dishes": [
              {
                "name": "frittata",
                "quantity": 2
              },
              {
                "name": "cappuccino",
                "quantity": 1
              }
            ]
          }
          ```
      
      ### Error Handling:
      - If the user selects a dish that is unavailable or provides an invalid dish name, respond gracefully and suggest alternative options.
        - Example: *"It seems that dish is currently unavailable. How about trying [alternative dish]?"*
      - Ensure that any errors from the API are communicated politely to the user, offering to retry or explore other options.
      

      Обратите внимание, что в инструкциях мы определяем общее поведение агента и указываем ему, на что он способен. Мы также включаем инструкции по конкретному поведению при размещении заказа, включая форму данных, ожидаемых API. Мы включаем эти сведения, чтобы убедиться, что агент работает должным образом.

    3. Сохраните изменения.

  3. Чтобы помочь пользователям, понять, для чего они могут использовать агент, добавьте начальные параметры общения:
    1. Откройте файл appPackage/declarativeAgent.json .

    2. После свойства instructions добавьте новое свойство с именем conversation_starters:

      "conversation_starters": [
        {
          "text": "What's for lunch today?"
        },
        {
          "text": "What can I order for dinner that is gluten-free?"
        }
      ]
      
    3. Полный файл выглядит следующим образом:

      {
        "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.0/schema.json",
        "version": "v1.0",
        "name": "Il Ristorante",
        "description": "Order the most delicious Italian dishes and drinks from the comfort of your desk.",
        "instructions": "$[file('instruction.txt')]",
        "conversation_starters": [
          {
            "text": "What's for lunch today?"
          },
          {
            "text": "What can I order for dinner that is gluten-free?"
          }
        ],
        "actions": [
          {
            "id": "menuPlugin",
            "file": "ai-plugin.json"
          }
        ]
      }
      
    4. Сохраните изменения.

Обновление URL-адреса API

Прежде чем протестировать декларативный агент, необходимо обновить URL-адрес API в файле спецификации API. Сейчас задан http://localhost:7071/api URL-адрес, который является URL-адресом, который Функции Azure использовать при локальном запуске. Тем не менее, так как вы хотите, чтобы Copilot вызывал API из облака, необходимо предоставить свой API в Интернете. Microsoft 365 Agents Toolkit автоматически предоставляет локальный API через Интернет, создавая туннель разработки. Каждый раз, когда вы начинаете отладку проекта, Microsoft 365 Agents Toolkit запускает новый туннель разработки и сохраняет его URL-адрес в переменной OPENAPI_SERVER_URL . Вы можете увидеть, как Microsoft 365 Agents Toolkit запускает туннель и сохраняет его URL-адрес в vscode/tasks.json файле в задаче Запуск локального туннеля :

{
  // Start the local tunnel service to forward public URL to local port and inspect traffic.
  // See https://aka.ms/teamsfx-tasks/local-tunnel for the detailed args definitions.
  "label": "Start local tunnel",
  "type": "teamsfx",
  "command": "debug-start-local-tunnel",
  "args": {
    "type": "dev-tunnel",
    "ports": [
      {
        "portNumber": 7071,
        "protocol": "http",
        "access": "public",
        "writeToEnvironmentFile": {
          "endpoint": "OPENAPI_SERVER_URL", // output tunnel endpoint as OPENAPI_SERVER_URL
        }
      }
    ],
    "env": "local"
  },
  "isBackground": true,
  "problemMatcher": "$teamsfx-local-tunnel-watch"
}

Чтобы использовать этот туннель, необходимо обновить спецификацию API, чтобы использовать переменную OPENAPI_SERVER_URL .

В Visual Studio Code:

  1. Откройте файл appPackage/apiSpecificationFile/ristorante.yml .

  2. Измените значение свойства servers.url на ${{OPENAPI_SERVER_URL}}/api.

  3. Измененный файл выглядит следующим образом:

    openapi: 3.0.0
    info:
      title: Il Ristorante menu API
      version: 1.0.0
      description: API to retrieve dishes and place orders for Il Ristorante.
    servers:
      - url: ${{OPENAPI_SERVER_URL}}/api
        description: Il Ristorante API server
    paths:
      ...trimmed for brevity
    
  4. Сохраните изменения.

Подключаемый модуль API завершен и интегрирован с декларативным агентом. Продолжайте тестирование агента в Microsoft 365 Copilot.

Тестирование декларативного агента с подключаемым модулем API в Microsoft 365 Copilot

Последним шагом является тестирование декларативного агента с подключаемым модулем API в Microsoft 365 Copilot.

В Visual Studio Code:

  1. На панели действий выберите Набор средств агентов Microsoft 365.

  2. В разделе Учетные записи убедитесь, что вы вошли в клиент Microsoft 365 с Microsoft 365 Copilot.

    Снимок экрана: раздел учетных записей microsoft 365 Agents Toolkit в Visual Studio Code.

  3. На панели действий выберите Запуск и отладка.

  4. Выберите отладку в конфигурации Copilot и начните отладку с помощью кнопки Начать отладку .

    Снимок экрана: конфигурация отладки в Copilot в Visual Studio Code.

  5. Visual Studio Code выполняет сборку и развертывание проекта в клиенте Microsoft 365 и открывает новое окно веб-браузера.

В веб-браузере:

  1. При появлении запроса войдите с учетной записью, принадлежающей вашему клиенту Microsoft 365, с Microsoft 365 Copilot.

  2. На боковой панели выберите Il Ristorante.

    Снимок экрана: интерфейс Microsoft 365 Copilot с выбранным агентом Il Ristorante.

  3. Выберите начальную строку беседы What's for lunch today? (Что на обед сегодня? ) и отправьте запрос.

    Снимок экрана: интерфейс Microsoft 365 Copilot с запросом на обед.

  4. При появлении запроса проверьте данные, отправляемые агентом в API, и подтвердите, используя кнопку Разрешить один раз .

    Снимок экрана: интерфейс Microsoft 365 Copilot с подтверждением обеда.

  5. Дождитесь ответа агента. Обратите внимание, что, хотя в нем отображаются ссылки на сведения, полученные из API, во всплывающем окне отображается только название блюда. Дополнительные сведения не отображаются, так как подключаемый модуль API не определяет шаблон адаптивной карточки.

    Снимок экрана: интерфейс Microsoft 365 Copilot с ответом на обед.

  6. Поместите заказ, введя в текстовое поле запроса: 1x спагетти, 1x чай со льдом и отправьте запрос.

  7. Изучите данные, отправляемые агентом в API, и продолжайте использовать кнопку Подтвердить .

    Снимок экрана: интерфейс Microsoft 365 Copilot с подтверждением заказа.

  8. Дождитесь, пока агент разместит заказ, и верните сводку заказа. Еще раз обратите внимание, что агент отображает сводку заказа в виде обычного текста, так как у него нет шаблона адаптивной карточки.

    Снимок экрана: интерфейс Microsoft 365 Copilot с ответом на заказ.

  9. Назад Visual Studio Code и остановить отладку.

  10. Перейдите на вкладку Терминал и закройте все активные терминалы.

    Снимок экрана: вкладка терминала Visual Studio Code с параметром закрытия всех терминалов.