Дата публикации
ai_products

Как подружить Terraform и Microsoft Foundry: DevOps-пайплайн для Hosted Agents без боли

Что нового

Microsoft обновила подход к развёртыванию Hosted Agents в Foundry и добавила второй путь деплоя:

  1. Деплой из исходников (preview)
    Теперь не обязательно собирать контейнер самому. Можно:

    • загрузить ZIP с исходным кодом;
    • приложить requirements.txt для Python 3.13 / 3.14 или .csproj для .NET 10;
    • выбрать режим:
      • remote_build — Foundry сам собирает зависимости;
      • bundled — вы загружаете уже собранный бандл, платформа просто разворачивает его.
  2. Новая схема описания версии агента

    • Для деплоя из исходников используется code_configuration.
    • Для деплоя контейнера — container_configuration.
    • Эти режимы взаимоисключающие для одной версии агента.
  3. Контент-адресуемое версионирование

    • Версия агента привязана к SHA‑256 ZIP-архива.
    • Если содержимое не изменилось, платформа не создаёт дубликаты — действует дедупликация.
  4. Изменились требования по ролям

    • Для деплоя Hosted Agent нужен Foundry Project Manager на уровне проекта.
    • Платформенный identity самого агента автоматически получает роль Foundry User.
    • azd и Foundry VS Code Toolkit настраивают это сами.
  5. Контейнерный путь никуда не делся
    Полностью поддерживается деплой через контейнеры:

    • вы сами собираете образ (Dockerfile);
    • пушите его в Azure Container Registry (ACR);
    • деплоите версию агента, привязанную к digest образа.

    Этот путь всё ещё нужен, если:

    • важен кастомный base image;
    • нужны системные пакеты;
    • требуется рантайм, отличный от Python/.NET.
  6. Terraform-скелет для Foundry нового типа
    Microsoft зафиксировала рекомендуемую базу инфраструктуры:

    • Foundry account как azurerm_cognitive_account с kind = "AIServices", project_management_enabled = true, custom_subdomain_name и системным managed identity;
    • Foundry project как azurerm_cognitive_account_project — именно он умеет Hosted Agents;
    • модельное развёртывание (например, gpt-4.1 с версией 2025-04-14, SKU GlobalStandard, capacity = 10);
    • ACR для контейнеров с ролью AcrPull на managed identity проекта;
    • Application Insights и базовый мониторинг (упоминается как часть полного шаблона);
    • чёткое разделение: Hosted Agents управляются через azd или Foundry SDK, а не Terraform.
  7. Стандартный DevOps-цикл для Hosted Agents
    Microsoft описывает полный контур:

    • Terraform поднимает Foundry, ACR, App Insights, RBAC.
    • CI/CD гоняет версии агентов, а не ветки кода.
    • Версия — это:
      • digest контейнера или ZIP + build-конфигурация;
      • CPU/память;
      • переменные окружения;
      • протоколы (responses, invocations и т.д.).
    • Оценка качества — жёсткий релиз-гейт, а не просто дэшборд.
    • Rollout/rollback делаются через разделение трафика по версиям.
    • Наблюдаемость — по версиям, а не по агенту в целом.
  8. Чётко зафиксирован ресурсный слой Foundry

    • Hosted Agents работают только на новом типе Foundry-проекта: azurerm_cognitive_account_project под azurerm_cognitive_account с kind = "AIServices".
    • Старый Azure AI Foundry Hub (azurerm_ai_foundry, azurerm_ai_foundry_project, kind = "Hub") не умеет Hosted Agents и имеет другие API.

Как это работает

Архитектура Foundry для Hosted Agents

Базовая схема ресурсов в Azure:

Resource group
└── Foundry account (Cognitive Services, kind=AIServices)
    ├── Model deployments (например, gpt-4.1)
    └── Foundry project
        ├── Hosted Agent: customer-support
        │   ├── Version v1 (image digest A, 100% трафика)
        │   └── Version v2 (image digest B, 0% трафика — канарейка)
        ├── Hosted Agent: webhook-handler
        ├── Evaluations
        ├── Connections (ACR, AI Search, Key Vault…)
        └── Toolbox (MCP)

Foundry account:

  • ресурс azurerm_cognitive_account с параметрами:
    • kind = "AIServices";
    • project_management_enabled = true — иначе проект не создастся;
    • custom_subdomain_name — нужен для Entra ID-аутентификации;
    • системный managed identity.

Foundry project:

  • ресурс azurerm_cognitive_account_project под этим аккаунтом;
  • это область для Hosted Agents, оценок, истории диалогов, подключений.

Если вместо этого создать azurerm_ai_foundry_project (Hub-модель), Hosted Agents, версии и трафик-сплит не будут доступны.

Что такое Hosted Agent

Hosted Agent — это не просто промпт с тулзами. Это ваш код, который Foundry запускает как управляемый сервис.

Под капотом:

  • вы собираете контейнерный образ или загружаете ZIP с исходниками;
  • образ попадает в ACR, ZIP — в Foundry;
  • Foundry Agent Service:
    • подтягивает контейнер;
    • создаёт изолированную среду исполнения на Azure Container Apps с VM-изоляцией для каждой сессии агента;
    • выдаёт агенту отдельный Microsoft Entra ID (agent identity);
    • поднимает выделенный endpoint для агента.

Агент может говорить по нескольким протоколам (до четырёх сразу):

  • Responses (.../protocols/openai/responses) — OpenAI-совместимый чатовый API, реализуется внутри контейнера.
  • Invocations (.../protocols/invocations) — JSON in / JSON out, удобно для вебхуков и неразговорных задач, тоже реализуется в контейнере.
  • A2A (.../protocols/a2a, preview) — открытый протокол Agent2Agent для делегирования между агентами разных фреймворков и вендоров. Endpoint даёт сама платформа.
  • Activity — протокол для Teams / Microsoft 365. Foundry сам мостит Responses → Activity, когда вы публикуете агента в M365-канал.

За рантайм, масштабирование, состояние сессий и жизненный цикл отвечает Microsoft. Ваша зона ответственности — образ и спецификация версии.

Версия агента как атомарный артефакт

Версия Hosted Agent — это зафиксированный снапшот конфигурации:

  • digest контейнерного образа (а не тег, чтобы не было дрейфа);
  • CPU и память для песочницы (например, 1 vCPU, 2 GiB RAM);
  • протоколы, которые реализует контейнер (responses, invocations);
  • переменные окружения;
  • дополнительные настройки (например, имя модельного деплоймента).

Чтобы изменить что угодно из этого списка, вы создаёте новую версию. Старые версии остаются, а платформа распределяет трафик по весам между ними. Отсюда вырастают:

  • безопасный canary rollout (0% → 10% → 100%);
  • мгновенный rollback — просто вернуть вес старой версии.

Типичная спецификация версии в repo — agent.yaml:

# agents/customer-support/agent.yaml
name: customer-support
container:
  image: ${ACR_LOGIN_SERVER}/customer-support  # digest резолвится при деплое
  cpu: 1
  memory: 2Gi
protocols:                                 # container_protocol_versions
  - responses
  # добавьте `invocations`, если контейнер умеет обрабатывать webhook-подобные payload'ы
env:
  # Платформа сама прокидывает FOUNDRY_PROJECT_ENDPOINT,
  # AZURE_AI_MODEL_DEPLOYMENT_NAME и APPLICATIONINSIGHTS_CONNECTION_STRING.
  # Здесь только то, что специфично для вашего агента.
  LOG_LEVEL: info
metadata:
  owner: support-team
  source_commit: ${GITHUB_SHA}

При деплое скрипт (например, scripts/deploy_agent_version.py) делает:

  1. Собирает Docker-образ.
  2. Пушит его в ACR.
  3. Получает digest.
  4. Создаёт версию агента через Foundry SDK или azd, подставляя digest в agent.yaml.

В режиме деплоя из исходников вместо container.image используется code_configuration с ZIP, requirements.txt или .csproj, и опцией remote_build / bundled.

Terraform-минимум для Hosted Agents

Ниже — тот самый «скелет», который нужен, чтобы Hosted Agent вообще мог жить на Foundry. Это не всё продакшен-окружение, но рабочая база.

# Foundry account (новая модель — требуется для Hosted Agents)
resource "azurerm_cognitive_account" "foundry" {
  name                       = "ai-${local.name}"
  resource_group_name        = azurerm_resource_group.main.name
  location                   = azurerm_resource_group.main.location
  kind                       = "AIServices"
  sku_name                   = "S0"
  project_management_enabled = true
  custom_subdomain_name      = "ai-${local.name}"   # требуется для AAD-auth

  identity {
    type = "SystemAssigned"
  }
}

# Модельное развёртывание, которое будет вызывать агент
resource "azurerm_cognitive_deployment" "gpt" {
  name                 = "gpt-4.1"   # стабильное имя — агенты пинятся к нему
  cognitive_account_id = azurerm_cognitive_account.foundry.id

  model {
    format  = "OpenAI"
    name    = "gpt-4.1"
    version = "2025-04-14"
  }

  sku {
    name     = "GlobalStandard"
    capacity = 10
  }
}

# Foundry project — область для Hosted Agents, оценок, разговоров
resource "azurerm_cognitive_account_project" "main" {
  name                 = "proj-${local.name}"
  cognitive_account_id = azurerm_cognitive_account.foundry.id
  location             = azurerm_resource_group.main.location

  identity {
    type = "SystemAssigned"
  }
}

# Container registry, куда пушится и откуда тянется образ агента
resource "azurerm_container_registry" "acr" {
  name                = "acr${replace(local.name, "-", "")}"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  sku                 = "Standard"
  admin_enabled       = false   # используем RBAC, а не admin user
}

# Managed identity проекта должен уметь тянуть образ из ACR
resource "azurerm_role_assignment" "project_acr_pull" {
  scope                = azurerm_container_registry.acr.id
  role_definition_name = "AcrPull"   # используйте Container Registry Repository Reader, если в ACR включён ABAC
  principal_id         = azurerm_cognitive_account_project.main.identity[0].principal_id
}

Ключевые моменты:

  • kind = "AIServices" + project_management_enabled = true + custom_subdomain_name делают аккаунт новой моделью Foundry.
  • Без project_management_enabled Terraform не создаст azurerm_cognitive_account_project.
  • Без custom_subdomain_name вы теряете endpoint-формат, на котором строится аутентификация через Entra ID.
  • Используйте azurerm_cognitive_account_project, а не azurerm_ai_foundry_project.
  • Имя модельного деплоймента (gpt-4.1) должно быть стабильным: код агента и agent.yaml привязываются к имени, а не к версии модели. Версию можно менять, имя — нет.
  • Managed identity проекта должен иметь право AcrPull, а не push. Push делает CI со своим identity.
  • Если в ACR включён ABAC, в CI нужно вызывать az acr build с --source-acr-auth-id [caller].

Где Terraform, а где SDK

Роль Terraform:

  • создать Foundry account и project;
  • развернуть модели (например, gpt-4.1);
  • поднять ACR и App Insights;
  • настроить RBAC и сетевую инфраструктуру.

Роль azd/Foundry SDK/скриптов:

  • собрать образ или упаковать ZIP;
  • запушить образ в ACR (для контейнерного пути);
  • создать версию Hosted Agent;
  • управлять трафиком между версиями;
  • запускать оценки качества.

Если AzureRM-провайдер ещё не знает про какой-то новый параметр или подресурс, Microsoft предлагает подключать azure/azapi как «заплатку»:

  • azapi_update_resource — пропатчить недостающие поля у ресурса AzureRM;
  • azapi_resource — описать ресурс, которого нет в AzureRM.

Полный DevOps-цикл

Microsoft описывает пять стадий доставки Hosted Agent:

  1. Infra provisioning

    • Артефакт: Terraform state.
    • Инструмент: terraform apply.
    • Типичные сбои: квоты, задержка в распространении RBAC, недоступный ACR.
  2. Image build & push (для контейнерного пути)

    • Артефакт: OCI-образ в ACR.
    • Инструменты: docker build или az acr build.
    • Сбои: слишком большой образ, уязвимости в base image.
  3. Создание версии агента

    • Артефакт: неизменяемая версия (digest + конфиг).
    • Инструменты: azd или Foundry SDK.
    • Сбои: неверные env-переменные, неправильная конфигурация протоколов.
  4. Оценка (evaluation)

    • Артефакт: датасет + конфиг градеров.
    • Инструмент: встроенные эвалюаторы Foundry (similarity, LLM-as-judge, safety, groundedness и т.д.).
    • Сбои: деградация качества или безопасности, которые должны ломать билд так же, как unit-тесты.
  5. Traffic shift & наблюдаемость

    • Артефакт: веса трафика по версиям + трейсинг в App Insights.
    • Инструменты: Foundry SDK + Azure Monitor.
    • Сбои: скрытое ухудшение качества, неправильный размер песочницы (слишком мало/много CPU и RAM).

Ключевая особенность: Hosted Agents — недетерминируемы по качеству. Два запуска terraform apply с одной и той же конфигурацией создают идентичные ресурсы. Два запроса к агенту с одинаковым входом могут дать разный ответ. Поэтому проверка качества через evaluation — такой же обязательный этап, как unit-тесты.

Структура репозитория

Рекомендуемый layout для проекта с несколькими агентами:

agent-platform/
├── infra/                          # Terraform (AIServices + project)
│   ├── modules/foundry-project/
│   └── environments/
│       ├── dev.tfvars
│       ├── staging.tfvars
│       └── prod.tfvars
├── agents/
│   ├── customer-support/
│   │   ├── Dockerfile
│   │   ├── src/                    # код агента (Python или C#)
│   │   ├── agent.yaml              # спецификация версии: образ, cpu/memory, протоколы, env
│   │   ├── evals/
│   │   │   ├── dataset.jsonl
│   │   │   └── graders.yaml
│   │   └── README.md
│   └── webhook-handler/
│       └── ...
├── scripts/
│   ├── deploy_agent_version.py     # build → push → create version → опционально сменить веса
│   ├── run_evals.py
│   └── promote_version.py          # переключение трафика между версиями
└── .github/workflows/
    ├── infra.yml                   # Terraform plan/apply
    ├── agent-pr.yml                # build, push, деплой кандидатной версии, запуск evals
    └── agent-release.yml           # промо проверенной версии в staging / prod

Две идеи:

  • инфраструктура и агенты живут в одном репозитории, но в разных директориях и с разными пайплайнами;
  • каждый агент — отдельная папка с собственным Dockerfile, кодом, agent.yaml и набором оценок.

Pull request обычно трогает одного агента, что упрощает ревью.

Что это значит для вас

Когда выбирать деплой из исходников

Новый путь деплоя по ZIP подойдёт, если:

  • вы пишете на Python 3.13 / 3.14 или .NET 10;
  • вам хватает стандартного окружения, не нужны экзотические системные пакеты;
  • вы хотите минимизировать возню с Docker и ACR в начале;
  • вам важна быстрая итерация: залили ZIP — получили новую версию.

Режим remote_build снимет с вас сборку зависимостей — Foundry сам поднимет окружение по requirements.txt или .csproj. Если вы хотите полный контроль над сборкой, но без Docker, можно использовать bundled и грузить уже собранный бандл.

Где это удобно:

  • быстрый прототип агента поддержки;
  • внутренние инструменты для команды (например, агент, который работает с внутренними API);
  • учебные и R&D-проекты, где важна скорость, а не кастомный рантайм.

Когда нужен контейнерный путь

Контейнерный деплой остаётся основой для продакшена, если:

  • вам нужен кастомный base image (например, с предустановленными библиотеками машинного обучения или специфическими CLI);
  • вы используете другие рантаймы, кроме Python/.NET;
  • нужна тонкая настройка системных пакетов, драйверов, утилит;
  • вы хотите встроить проверку безопасности образов в существующий DevSecOps-процесс.

В этом сценарии Terraform настраивает Foundry и ACR, а CI:

  • собирает Docker-образ;
  • пушит его в ACR;
  • создаёт версию Hosted Agent через SDK;
  • запускает evals и, если всё хорошо, продвигает версию дальше по окружениям.

Как строить пайплайн на практике

  1. Разделите инфраструктуру и код агентов

    • Terraform живёт в infra/ и крутится в infra.yml.
    • Код агентов и их конфигурации — в agents/ с отдельными workflow.
  2. Считайте версию агента главным артефактом

    • Не деплойте «ветку main», деплойте конкретную версию: digest образа + agent.yaml.
    • Храните ссылку на commit (source_commit) внутри версии, чтобы понимать, что именно крутится в проде.
  3. Оценка качества как релиз-гейт

    • Запускайте run_evals.py автоматически после создания новой версии.
    • Если метрики хуже порога — ломайте билд, не выпускайте версию дальше.
    • Считайте это таким же обязательным шагом, как unit-тесты.
  4. Промоушен через манифест

    • Описывайте, какая версия должна быть в dev/staging/prod, в отдельном манифесте.
    • promote_version.py читает манифест и меняет веса трафика.
    • Rollback — это просто откат манифеста, без пересборки.
  5. Работайте с трафиком по версиям, а не по окружениям

    • Для канарейки: 0% → 10% → 100% трафика на новую версию.
    • Для rollback: вернуть 100% на старую версию.
  6. Смотрите на метрики по версиям

    • Во время канарейки две версии обрабатывают запросы одновременно.
    • Если смотреть только агрегированные метрики по агенту, вы получите «усреднённую» картину, которая скрывает проблемы.
    • Настройте дэшборды в App Insights так, чтобы фильтровать по версии.

Доступность и ограничения

  • Hosted Agents и часть связанных возможностей (A2A, некоторые режимы деплоя и маршрутизации) находятся в статусе preview. Поведение и API могут меняться.
  • Foundry работает в Azure, поэтому нужен доступ к соответствующим регионам Azure и к порталу ai.azure.com.
  • Для команд в России может потребоваться VPN и юридическая оценка использования Azure, в зависимости от корпоративной политики и регуляторных требований.

Место на рынке

Microsoft Foundry с Hosted Agents конкурирует не с одной моделью вроде GPT-4.1, а с целыми платформами для агентных приложений и MLOps-оркестрации.

По конкретным параметрам из описания:

  • Управление версиями
    Foundry даёт контент-адресуемое версионирование по SHA‑256 ZIP-архива и digest контейнера. Это ближе к подходу OCI-образов и даёт предсказуемость: одна и та же версия — это всегда один и тот же артефакт.

  • Трафик-сплит по версиям
    Встроенная поддержка взвешенного распределения трафика между версиями превращает canary и rollback в операцию изменения конфигурации, без пересборки и перезапуска.

  • Identity per agent
    Каждый Hosted Agent получает собственный Microsoft Entra ID. Это упрощает настройку RBAC к downstream-сервисам по сравнению с общим сервисным аккаунтом.

  • Интеграция с Azure
    Terraform-конфигурация использует стандартные ресурсы Azure (azurerm_cognitive_account, azurerm_container_registry, azurerm_cognitive_deployment, azurerm_cognitive_account_project) и дополняется azapi, когда AzureRM не успевает за новыми возможностями. Для команд, уже живущих в Azure, это снижает порог входа.

Сравнительных цифр по скорости, стоимости вызовов или размеру контекста для Hosted Agents относительно других платформ в описании нет. Зато чётко обозначена ставка на DevOps-паттерны: immutable версии, eval как релиз-гейт, трафик-сплит и пер-версионная наблюдаемость.

Для команд, которые уже используют Terraform, Azure и Azure DevOps/GitHub Actions, Foundry Hosted Agents дают понятный путь к продакшену AI-агентов без изобретения собственной платформы.

Установка / Как запустить

Ниже — практический минимум, чтобы завести Hosted Agent на новом Foundry-проекте.

1. Подготовить Terraform-инфраструктуру

Создайте модуль с ресурсами из примера выше и параметризуйте local.name. Разведите окружения по *.tfvars:

infra/
  modules/
    foundry-project/
      main.tf
  environments/
    dev.tfvars
    staging.tfvars
    prod.tfvars

В infra.yml (GitHub Actions) настройте:

  • terraform plan на каждый PR с выводом в комментарий;
  • terraform apply только при merge в ветку окружения.

2. Организовать репозиторий под агентов

Создайте структуру:

agents/
  customer-support/
    Dockerfile
    src/
    agent.yaml
    evals/
      dataset.jsonl
      graders.yaml
    README.md
scripts/
  deploy_agent_version.py
  run_evals.py
  promote_version.py
.github/workflows/
  agent-pr.yml
  agent-release.yml

3. Описать версию агента

В agents/customer-support/agent.yaml задайте:

  • имя агента;
  • ссылку на образ (без digest, он подставится при деплое);
  • ресурсы (CPU/память);
  • протоколы;
  • env-переменные;
  • метаданные (например, commit).

Пример уже был выше:

name: customer-support
container:
  image: ${ACR_LOGIN_SERVER}/customer-support
  cpu: 1
  memory: 2Gi
protocols:
  - responses
env:
  LOG_LEVEL: info
metadata:
  owner: support-team
  source_commit: ${GITHUB_SHA}

4. Настроить пайплайны агентов

В agent-pr.yml:

  • при PR в ветку агента:
    • собрать Docker-образ;
    • запушить в ACR;
    • создать кандидатную версию агента через deploy_agent_version.py;
    • запустить run_evals.py и упасть, если качество ниже порога.

В agent-release.yml:

  • при релизном событии (tag/merge в release-ветку):
    • взять прошедшую eval версию;
    • обновить манифест окружения;
    • вызвать promote_version.py, чтобы:
      • в staging — дать, например, 100% трафика новой версии;
      • в prod — делать пошаговый canary (0% → 10% → 100%).

5. Подключить наблюдаемость

Foundry сам шлёт OpenTelemetry-трейсы агентов в связанный Application Insights. Вам остаётся:

  • завести дэшборды с фильтрацией по версии агента;
  • настроить алерты по задержке, стоимости, ошибкам и качественным метрикам во время канареек;
  • использовать эти же метрики как аргумент при решении: оставлять новую версию или откатываться.

С этой схемой разрыв между terraform apply и «агент стабильно отвечает клиентам в проде» закрывается стандартным DevOps-контуром, а не набором разрозненных скриптов.


Читайте также