- Дата публикации
Как подружить Terraform и Microsoft Foundry: DevOps-пайплайн для Hosted Agents без боли
Что нового
Microsoft обновила подход к развёртыванию Hosted Agents в Foundry и добавила второй путь деплоя:
-
Деплой из исходников (preview)
Теперь не обязательно собирать контейнер самому. Можно:- загрузить ZIP с исходным кодом;
- приложить
requirements.txtдля Python 3.13 / 3.14 или.csprojдля .NET 10; - выбрать режим:
remote_build— Foundry сам собирает зависимости;bundled— вы загружаете уже собранный бандл, платформа просто разворачивает его.
-
Новая схема описания версии агента
- Для деплоя из исходников используется
code_configuration. - Для деплоя контейнера —
container_configuration. - Эти режимы взаимоисключающие для одной версии агента.
- Для деплоя из исходников используется
-
Контент-адресуемое версионирование
- Версия агента привязана к SHA‑256 ZIP-архива.
- Если содержимое не изменилось, платформа не создаёт дубликаты — действует дедупликация.
-
Изменились требования по ролям
- Для деплоя Hosted Agent нужен Foundry Project Manager на уровне проекта.
- Платформенный identity самого агента автоматически получает роль Foundry User.
azdи Foundry VS Code Toolkit настраивают это сами.
-
Контейнерный путь никуда не делся
Полностью поддерживается деплой через контейнеры:- вы сами собираете образ (Dockerfile);
- пушите его в Azure Container Registry (ACR);
- деплоите версию агента, привязанную к digest образа.
Этот путь всё ещё нужен, если:
- важен кастомный base image;
- нужны системные пакеты;
- требуется рантайм, отличный от Python/.NET.
-
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, SKUGlobalStandard, capacity = 10); - ACR для контейнеров с ролью
AcrPullна managed identity проекта; - Application Insights и базовый мониторинг (упоминается как часть полного шаблона);
- чёткое разделение: Hosted Agents управляются через
azdили Foundry SDK, а не Terraform.
- Foundry account как
-
Стандартный DevOps-цикл для Hosted Agents
Microsoft описывает полный контур:- Terraform поднимает Foundry, ACR, App Insights, RBAC.
- CI/CD гоняет версии агентов, а не ветки кода.
- Версия — это:
- digest контейнера или ZIP + build-конфигурация;
- CPU/память;
- переменные окружения;
- протоколы (
responses,invocationsи т.д.).
- Оценка качества — жёсткий релиз-гейт, а не просто дэшборд.
- Rollout/rollback делаются через разделение трафика по версиям.
- Наблюдаемость — по версиям, а не по агенту в целом.
-
Чётко зафиксирован ресурсный слой 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.
- Hosted Agents работают только на новом типе Foundry-проекта:
Как это работает
Архитектура 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) делает:
- Собирает Docker-образ.
- Пушит его в ACR.
- Получает digest.
- Создаёт версию агента через 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_enabledTerraform не создаст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:
-
Infra provisioning
- Артефакт: Terraform state.
- Инструмент:
terraform apply. - Типичные сбои: квоты, задержка в распространении RBAC, недоступный ACR.
-
Image build & push (для контейнерного пути)
- Артефакт: OCI-образ в ACR.
- Инструменты:
docker buildилиaz acr build. - Сбои: слишком большой образ, уязвимости в base image.
-
Создание версии агента
- Артефакт: неизменяемая версия (digest + конфиг).
- Инструменты:
azdили Foundry SDK. - Сбои: неверные env-переменные, неправильная конфигурация протоколов.
-
Оценка (evaluation)
- Артефакт: датасет + конфиг градеров.
- Инструмент: встроенные эвалюаторы Foundry (similarity, LLM-as-judge, safety, groundedness и т.д.).
- Сбои: деградация качества или безопасности, которые должны ломать билд так же, как unit-тесты.
-
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 и, если всё хорошо, продвигает версию дальше по окружениям.
Как строить пайплайн на практике
-
Разделите инфраструктуру и код агентов
- Terraform живёт в
infra/и крутится вinfra.yml. - Код агентов и их конфигурации — в
agents/с отдельными workflow.
- Terraform живёт в
-
Считайте версию агента главным артефактом
- Не деплойте «ветку main», деплойте конкретную версию: digest образа +
agent.yaml. - Храните ссылку на commit (
source_commit) внутри версии, чтобы понимать, что именно крутится в проде.
- Не деплойте «ветку main», деплойте конкретную версию: digest образа +
-
Оценка качества как релиз-гейт
- Запускайте
run_evals.pyавтоматически после создания новой версии. - Если метрики хуже порога — ломайте билд, не выпускайте версию дальше.
- Считайте это таким же обязательным шагом, как unit-тесты.
- Запускайте
-
Промоушен через манифест
- Описывайте, какая версия должна быть в dev/staging/prod, в отдельном манифесте.
promote_version.pyчитает манифест и меняет веса трафика.- Rollback — это просто откат манифеста, без пересборки.
-
Работайте с трафиком по версиям, а не по окружениям
- Для канарейки: 0% → 10% → 100% трафика на новую версию.
- Для rollback: вернуть 100% на старую версию.
-
Смотрите на метрики по версиям
- Во время канарейки две версии обрабатывают запросы одновременно.
- Если смотреть только агрегированные метрики по агенту, вы получите «усреднённую» картину, которая скрывает проблемы.
- Настройте дэшборды в 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-контуром, а не набором разрозненных скриптов.