Что особенного в деплое агента
Прежде чем выбирать площадку, надо понять требования — они отличаются и от классического веб-приложения, и от «настоящего» ML-сервиса.
| Требование | Почему у агента так |
|---|---|
| GPU не нужен | Инференс — у провайдера LLM. Твой код только оркеструет |
| Мало CPU/RAM | Основное время процесс ждёт сеть, а не считает |
| Долгие запросы | 10–60 секунд на ответ; фоновые задачи — минуты |
| Много ждущих соединений | Стриминг/WebSocket держат соединение открытым |
| Критичные секреты | Утёкший API-ключ = чужие счета на твоей карте |
| Исходящая сеть обязательна | Без доступа к API провайдера агент бесполезен |
Полезная переустановка ожиданий: разворачивать агента не сложнее, чем обычный FastAPI-бэкенд, и гораздо проще, чем модель на GPU. Не ищи ML-специфичные платформы и не закладывай дорогое железо. Главные вопросы при выборе площадки — не «сколько vCPU», а «какой максимальный таймаут запроса», «как хранятся секреты» и «переживёт ли фоновая задача».
База: Docker-образ
Docker — общий знаменатель почти всех площадок: собрал образ один раз, запускаешь где угодно. Для агента образ простой, но есть нюансы, которые отличают учебный Dockerfile от production-ready.
FROM python:3.12-slim
WORKDIR /app
# 1. Сначала ТОЛЬКО зависимости — слой закэшируется и не будет
# пересобираться при каждом изменении кода
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 2. Потом код (меняется часто → отдельный слой)
COPY . .
# 3. Не root: если контейнер скомпрометируют, ущерб меньше
RUN useradd -m appuser && chown -R appuser /app
USER appuser
# 4. Health check — платформа должна знать, жив ли сервис
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s \
CMD python -c "import httpx; httpx.get('http://localhost:8000/health').raise_for_status()"
EXPOSE 8000
# 5. Секреты НЕ в образ! Только через переменные окружения при запуске
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Самая дорогая ошибка деплоя. ENV OPENAI_API_KEY=sk-... в Dockerfile, ключ в .env, закоммиченном в git, или в слое образа — всё это утечка: образ можно скачать и распаковать, историю git — прочитать (удаление файла новым коммитом не убирает его из истории). Утёкший ключ находят боты за минуты, и счёт приходит тебе. Правильно: секреты передаются снаружи при запуске — через переменные окружения платформы или менеджер секретов. В репозитории — только .env.example без значений, а .env — в .gitignore.
Куда деплоить: четыре варианта
Площадки различаются по компромиссу «простота ↔ контроль» и — критично для агентов — по ограничению на длительность запроса.
Ключевой критерий выбора для агента: максимальная длительность запроса. У функций-as-a-service (в частности AWS Lambda) есть жёсткий потолок времени выполнения, и глубокий research на несколько минут в него может не влезть — функция будет убита на середине. Плюс на serverless сложнее стриминг и WebSocket (нужны отдельные механизмы), а холодный старт добавляет секунды к первому запросу — заметно для интерактивного чата. Вывод: короткие задачи и вебхуки — можно; долгий интерактивный агент — либо площадка с постоянно живущим процессом (Railway/VPS), либо job-паттерн (урок про FastAPI), где HTTP лишь ставит задачу. Конкретные лимиты и цены у всех платформ меняются — сверяйся с актуальной документацией.
Обязательный минимум прода
Развернуть — мало. Есть набор вещей, без которых деплой считается незавершённым.
- Секреты через окружение. Ключи задаются в настройках платформы или менеджере секретов, не в коде и не в образе. В репозитории — только
.env.example. - Health check. Эндпоинт
/health, по которому платформа понимает, жив ли контейнер, и перезапускает при зависании. - Graceful shutdown. При деплое старый процесс должен доработать текущие запросы, а не оборвать их посреди ответа агента.
- Конфиг через переменные. Модель, лимиты, таймауты, адреса — из окружения, чтобы менять без пересборки образа.
- Логи в stdout. Пиши JSON-логи в stdout — платформа сама их соберёт (урок про логирование). Не пиши в файлы внутри контейнера: он эфемерен.
- Observability включена. Трейсинг и метрики (первый раздел модуля) должны работать с первого дня в проде, а не «когда понадобится».
import os
from fastapi import FastAPI
app = FastAPI()
# конфиг — из окружения, с разумными дефолтами (менять без пересборки)
MODEL = os.environ["AGENT_MODEL"] # обязателен → упадём сразу
API_KEY = os.environ["LLM_API_KEY"] # НИКОГДА не хардкодить
TIMEOUT_S = float(os.getenv("AGENT_TIMEOUT_S", "60"))
@app.get("/health")
async def health():
"""Живой ли процесс — для платформы/оркестратора."""
return {"status": "ok"}
@app.get("/ready")
async def ready():
"""Готов ли ОБСЛУЖИВАТЬ: проверяем зависимости (БД, кэш).
Внешний LLM-провайдер здесь лучше НЕ дёргать на каждый чек —
иначе его сбой начнёт перезапускать твои живые контейнеры."""
return {"status": "ready" if await db.ping() else "degraded"}
Автоматизируй выкатку так, чтобы в прод не мог попасть непроверенный агент: push → unit + integration тесты (раздел тестирования) → regression на golden dataset (раздел оценки) → сборка образа → деплой. Красный гейт блокирует релиз. И помни про поэтапную раскатку из урока A/B: canary → 10% → 100% с guardrail-метриками и возможностью быстрого отката. Именно связка «тесты в CI + постепенный rollout + мониторинг» превращает деплой из страшного события в рутину.
Синтез: что делает агента production-ready
Этим уроком закрывается модуль. Соберём всё, что мы построили вокруг агента, в одну картину:
┌─────────────── PRODUCTION-READY АГЕНТ ───────────────┐
│ │
① OBSERVABILITY трейсы (LangSmith/Langfuse/OTel) · structured логи · дашборды
«я вижу, что происходит»
↓
② ОЦЕНКА КАЧЕСТВА offline-метрики · human eval · LLM-judge · A/B · regression
«я знаю, хорошо ли он работает, и не даю деградировать»
↓
③ ТЕСТИРОВАНИЕ unit (компоненты) · integration (стыки) · datasets · trajectory
«код и стыки корректны, путь агента разумен»
↓
④ НАДЁЖНОСТЬ retry · fallback · rate limiting · timeouts · degradation
«переживает сбои провайдера, лимиты и зависания»
↓
⑤ ОПТИМИЗАЦИЯ контекст · prompt caching · параллелизация · модель под задачу
«быстро и по разумной цене»
↓
⑥ ДЕПЛОЙ Docker · площадка · секреты · health · CI/CD · rollout
«работает в мире, выкатывается безопасно»
│ │
└───────── разница между «работает у меня» и «работает у всех» ─────────┘
Агент из модулей 03–05 умел решать задачу. Модуль 06 добавил всё, что превращает его в продукт: вы видите его работу, измеряете качество и не даёте ему деградировать, тестируете код, переживаете аварии, работаете быстро и экономно и выкатываете безопасно. Ни один из этих слоёв не про «умность» агента — все они про то, чтобы на него можно было положиться. Именно это отличает демо от системы, которой пользуются люди.
Типичные ошибки
Ключ в Dockerfile/.env в git — утечка (образ распаковывается, история git читается). Боты находят за минуты, счёт приходит тебе. Только переменные окружения снаружи.
Функцию убивают на середине research'а, стриминг и WebSocket работают плохо, холодный старт бьёт по TTFT. Проверяй максимальную длительность запроса до выбора площадки.
Зависший контейнер не перезапустится, а деплой оборвёт ответы пользователей на середине. Оба механизма — обязательный минимум.
Контейнер эфемерен — логи исчезнут при рестарте и не попадут в агрегатор. Пиши JSON в stdout.
Выкатка сразу на 100% без regression-гейта — способ узнать о поломке от пользователей. CI-гейт + canary + мониторинг + быстрый откат.
Шпаргалка
АГЕНТ = обычный I/O-bound веб-сервис (НЕ ML-сервис!): GPU не нужен, CPU/RAM мало
главные вопросы к площадке: МАКС. ДЛИТЕЛЬНОСТЬ ЗАПРОСА · секреты · фоновые задачи
специфика: долгие запросы (10–60с) · много ждущих соединений · критичные ключи
DOCKER (общий знаменатель):
зависимости ОТДЕЛЬНЫМ слоем (кэш) → потом код · non-root · HEALTHCHECK · EXPOSE
🔒 СЕКРЕТЫ НЕ В ОБРАЗ И НЕ В GIT (образ распаковывается, история git читается!)
только env снаружи · в репо — .env.example, .env в .gitignore
ПЛОЩАДКИ (простота → контроль):
Railway/Render — PaaS, git push, процесс живёт постоянно, ок стриминг/WS
→ MVP, старт · ✗ дороже на масштабе
Modal — serverless для Python/AI, инфра из кода, автомасштаб, длинные задачи ок
→ батчи, неравномерная нагрузка · ✗ холодный старт, lock-in
AWS Lambda — платишь за вызовы, масштаб из коробки
⚠️ ЖЁСТКИЙ ЛИМИТ ВРЕМЕНИ · стриминг/WS сложно · холодный старт
→ короткие задачи, вебхуки · долгий агент МОЖЕТ НЕ ВЛЕЗТЬ
VPS/Kubernetes — полный контроль, дешевле на масштабе, приватность
→ зрелый прод, комплаенс · ✗ нужен DevOps
СТРАТЕГИЯ: начни с простого → переезжай при упоре в цену/контроль (Docker удешевляет переезд)
МИНИМУМ ПРОДА: секреты через env · /health + /ready · graceful shutdown ·
конфиг из переменных · логи JSON в STDOUT (не в файл — контейнер эфемерен) ·
observability с первого дня
⚠️ в /ready не дёргать LLM-провайдер — его сбой начнёт рестартить твои живые контейнеры
CI/CD: push → unit+integration → REGRESSION на golden → образ → деплой
+ canary → 10% → 100% с guardrails и быстрым откатом
ГРАБЛИ: секреты в образе/git · serverless-лимит для долгого агента ·
нет health/graceful shutdown · логи в файл · деплой без тестов и canary
Практическое задание
Задание: разверни агента
- Напиши Dockerfile для агента из модулей 03–05: отдельный слой зависимостей, non-root, healthcheck. Собери образ и запусти локально, передав ключи через
-e. - Проверь на утечки: нет ли ключей в Dockerfile, в слоях образа, в истории git? Есть ли
.envв.gitignoreи.env.exampleв репозитории? - Замерь максимальное время ответа своего агента. Влезет ли оно в лимит выбранной serverless-платформы? Если нет — какой паттерн применишь (job-паттерн или другая площадка)?
- Выбери площадку под свой сценарий и обоснуй по таблице: что важнее — скорость старта, цена, контроль, приватность?
- Добавь
/healthи/ready. Что проверяешь в ready, а что намеренно НЕ проверяешь и почему? - Разверни агента на выбранной площадке. Убедись, что: секреты заданы снаружи, логи видны в панели, трейсинг работает в проде.
- Со звёздочкой: собери CI/CD-пайплайн: тесты → regression-гейт на golden dataset → сборка → деплой. Проверь, что сломанный regression блокирует выкатку.
Что дальше
Раздел «Оптимизация и деплой» закрыт, а с ним — вся теория модуля 06. Твой агент теперь наблюдаем, измерим, протестирован, надёжен, оптимизирован и развёрнут. Остался финальный аккорд — проект модуля: взять агента из модуля 03 и довести его до настоящего прода — с полным мониторингом, тестами и CI/CD-пайплайном, собрав все шесть слоёв воедино.