Добавление приложения App Service как компонента в службу агента Foundry (Node.js)

В этом руководстве вы узнаете, как предоставить функциональные возможности приложения Express.js с помощью OpenAPI, добавить его в службу агента Foundry и взаимодействовать с приложением с помощью естественного языка в песочнице агентов.

Если веб-приложение уже имеет полезные функции, такие как покупки, бронирование отелей или управление данными, это легко сделать эти возможности доступными агенту ИИ в Службе агента Foundry. Просто добавив в приложение схему OpenAPI, агент может понять и использовать возможности приложения при реагировании на запросы пользователей. Это означает, что ваше приложение может сделать все, что может сделать агент ИИ, с минимальными усилиями, помимо создания конечной точки OpenAPI для вашего приложения. В этом руководстве вы начнёте с простого приложения для списков to-do. К концу вы сможете создавать, обновлять и управлять задачами с агентом с помощью общения ИИ.

Снимок экрана: игровая площадка агентов в середине беседы, которая выполняет действия с помощью средства OpenAPI.

  • Добавьте функции OpenAPI в веб-приложение.
  • Убедитесь, что схема OpenAPI совместима со службой агента Foundry.
  • Зарегистрируйте приложение в качестве средства OpenAPI в службе агента Foundry.
  • Проверьте агент на игровой площадке агентов.

Prerequisites

В этом руководстве предполагается, что вы работаете с примером, используемым в руководстве. Развертывание веб-приложения Node.js + MongoDB в Azure.

По крайней мере, откройте образец приложения в GitHub Codespaces и разверните приложение, запустив команду azd up.

Открыть в GitHub Codespaces

Добавление функций OpenAPI в веб-приложение

  1. В терминале пространства кода добавьте в проект пакет NuGet swagger-jsdoc NPM:

    npm install swagger-jsdoc
    
  2. Открытие маршрутов/index.js. В нижней части файла выше module.exports = router; добавьте следующие функции API. Чтобы обеспечить их совместимость со службой агента Foundry, необходимо указать operationId свойство в заметке @swagger (см. раздел "Использование службы агента Foundry" с указанными средствами OpenAPI: предварительные требования).

    router.get('/schema', function(req, res, next) {
      try {
        const swaggerJsdoc = require('swagger-jsdoc');
    
        res.json(
          swaggerJsdoc(
            {
              definition: {
                openapi: '3.0.0',
                servers: [
                  {
                    url: `${req.protocol}://${req.get('host')}`,
                    description: 'Task API',
                  },
                ],
              },
              apis: ['./routes/*.js'],
            }
          )
        );
      } catch (error) {
        res.status(500).json({ error: error.message });
      }
    });
    
    /**
     * @swagger
     * /api/tasks:
     *   get:
     *     summary: Get all tasks
     *     operationId: getAllTasks
     *     responses:
     *       200:
     *         description: List of tasks
     */
    router.get('/api/tasks', async function(req, res, next) {
      try {
        const tasks = await Task.find();
        res.json(tasks);
      } catch (error) {
        res.status(500).json({ error: error.message });
      }
    });
    
    /**
     * @swagger
     * /api/tasks/{id}:
     *   get:
     *     summary: Get task by ID
     *     operationId: getTaskById
     *     parameters:
     *       - in: path
     *         name: id
     *         required: true
     *         schema:
     *           type: string
     *     responses:
     *       200:
     *         description: Task details
     */
    router.get('/api/tasks/:id', async function(req, res, next) {
      try {
        const task = await Task.findById(req.params.id);
        res.json(task);
      } catch (error) {
        res.status(404).json({ error: error.message });
      }
    });
    
    /**
     * @swagger
     * /api/tasks:
     *   post:
     *     summary: Create a new task
     *     operationId: createTask
     *     requestBody:
     *       required: true
     *       content:
     *         application/json:
     *           schema:
     *             type: object
     *             properties:
     *               taskName:
     *                 type: string
     *     responses:
     *       201:
     *         description: Task created
     */
    router.post('/api/tasks', async function(req, res, next) {
      try {
        // Set createDate to current timestamp when creating a task
        const taskData = {
          ...req.body,
          createDate: new Date()
        };
    
        const task = new Task(taskData);
        await task.save();
        res.status(201).json(task);
      } catch (error) {
        res.status(400).json({ error: error.message });
      }
    });
    
    /**
     * @swagger
     * /api/tasks/{id}:
     *   put:
     *     summary: Update a task
     *     operationId: updateTask
     *     parameters:
     *       - in: path
     *         name: id
     *         required: true
     *         schema:
     *           type: string
     *     requestBody:
     *       required: true
     *       content:
     *         application/json:
     *           schema:
     *             type: object
     *             properties:
     *               taskName:
     *                 type: string
     *               completed:
     *                 type: boolean
     *     responses:
     *       200:
     *         description: Task updated
     */
    router.put('/api/tasks/:id', async function(req, res, next) {
      try {
        // If completed is being set to true, also set completedDate
        if (req.body.completed === true) {
          req.body.completedDate = new Date();
        }
    
        const task = await Task.findByIdAndUpdate(req.params.id, req.body, { new: true });
        res.json(task);
      } catch (error) {
        res.status(400).json({ error: error.message });
      }
    });
    
    /**
     * @swagger
     * /api/tasks/{id}:
     *   delete:
     *     summary: Delete a task
     *     operationId: deleteTask
     *     parameters:
     *       - in: path
     *         name: id
     *         required: true
     *         schema:
     *           type: string
     *     responses:
     *       200:
     *         description: Task deleted
     */
    router.delete('/api/tasks/:id', async function(req, res, next) {
      try {
        const task = await Task.findByIdAndDelete(req.params.id);
        res.json({ message: 'Task deleted successfully', task });
      } catch (error) {
        res.status(404).json({ error: error.message });
      }
    });
    

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

  3. В терминале пространства кода запустите приложение, используя npm start.

  4. Выберите Открыть в браузере.

  5. Просмотрите схему OpenAPI, добавив /schema в URL-адрес.

  6. Вернитесь в терминал codespace, зафиксируйте изменения (метод GitHub Actions) или запустите azd up (метод Azure Developer CLI).

  7. После развертывания изменений перейдите к https://<your-app's-url>/schema схеме и скопируйте ее позже.

Создание агента в Microsoft Foundry

Замечание

В этих шагах используется новый портал Foundry.

  1. На портале Foundry в правом верхнем меню выберите New Foundry.

  2. Если это первый раз на новом портале Foundry, выберите имя проекта и нажмите кнопку "Создать проект".

  3. Присвойте проекту имя и нажмите кнопку "Создать".

  4. Нажмите кнопку "Начать сборку", а затем создайте агент.

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

    Обратите внимание на модели, которые можно использовать и доступные регионы.

  6. В песочнице агента разверните Инструменты и выберите Добавить>настраиваемый>инструмент OpenAPI>Создать.

  7. Присвойте инструменту имя и описание. В поле схемы OpenAPI 3.0+ вставьте скопированную ранее схему.

  8. Нажмите "Создать инструмент".

  9. Нажмите кнопку "Сохранить".

Подсказка

В этом руководстве средство OpenAPI настроено для анонимного вызова приложения без проверки подлинности. Для рабочих сценариев необходимо защитить инструмент с помощью идентификации управляемой учетной записи. Пошаговые инструкции см. в разделе "Безопасные конечные точки OpenAPI" для службы агента Foundry.

Протестируйте агент

  1. В инструкциях приведены некоторые простые инструкции, например "Используйте средство todosApp для управления задачами".

  2. Свяжитесь с агентом с учетом следующих вариантов запроса:

    • Показать мне все задачи.
    • Создайте задачу под названием "Придумать три шутки салата".
    • Измените это на "Придумать с тремя шутками стука-стука".

    Снимок экрана: игровая площадка агентов в середине беседы, которая выполняет действия с помощью средства OpenAPI.

Рекомендации по обеспечению безопасности

При предоставлении API-интерфейсов с помощью OpenAPI в Службе приложений Azure следуйте приведенным ниже рекомендациям по обеспечению безопасности.

  • Проверка подлинности и авторизация. Защита конечных точек OpenAPI с помощью проверки подлинности Microsoft Entra. Пошаговые инструкции см. в разделе "Безопасные конечные точки OpenAPI" для службы агента Foundry. Кроме того, вы можете защитить свои конечные точки с помощью Azure API Management и идентификатора Microsoft Entra ID, обеспечив доступ только для авторизованных пользователей или агентов.
  • Проверьте входные данные: Всегда проверяйте входящие данные, чтобы предотвратить недопустимые или вредоносные входные данные. Для приложений Node.js используйте библиотеки, такие как express-validator , для применения правил проверки данных. Обратитесь к их документации для получения рекомендаций и деталей реализации.
  • Используйте ПРОТОКОЛ HTTPS: В примере используется служба приложений Azure, которая по умолчанию применяет ПРОТОКОЛ HTTPS и предоставляет бесплатные СЕРТИФИКАТЫ TLS/SSL для шифрования данных во время передачи.
  • Ограничение CORS: Ограничить общий доступ к ресурсам между источниками (CORS) только доверенным доменам. Дополнительные сведения см. в разделе "Включение CORS".
  • Применение ограничения скорости:Используйте службу управления API или службу пользовательского промежуточного слоя, чтобы предотвратить злоупотребления и атаки типа "отказ в обслуживании".
  • Скрытие конфиденциальных конечных точек: Избегайте предоставления внутренних или административных API в схеме OpenAPI.
  • Просмотрите схему OpenAPI: Убедитесь, что схема OpenAPI не раскрывает конфиденциальную информацию (например, внутренние ссылки, секреты или детали реализации).
  • Обновление зависимостей: Регулярно обновляйте пакеты NuGet и отслеживайте рекомендации по безопасности.
  • Ведение журнала и мониторинг активности: Включите ведение журнала и мониторинг доступа для обнаружения подозрительной активности.
  • Используйте управляемые удостоверения: При вызове других служб Azure используйте управляемые удостоверения вместо жестко закодированных учетных данных.

Дополнительные сведения см. в статье "Защита приложения службы приложений " и рекомендации по обеспечению безопасности REST API.

Следующий шаг

Теперь вы настроили приложение App Service для использования в качестве инструмента для службы агента Foundry. Взаимодействуйте с API вашего приложения через естественный язык на платформе для агентов. Здесь вы можете продолжать добавлять функции в агент на портале Foundry, интегрировать его в собственные приложения с помощью пакета SDK Microsoft Foundry или REST API или развернуть его в составе более крупного решения. Агенты, созданные в Microsoft Foundry, можно запускать в облаке, интегрировать в чат-боты или внедрять в веб-приложения и мобильные приложения.

Чтобы выполнить следующий шаг и узнать, как запустить агент непосредственно в Службе приложений Azure, ознакомьтесь со следующим руководством.

Дополнительные ресурсы