Что получится в результате
Соберем production-like запуск ИИ-агента на VPS или выделенном сервере. Агент будет работать как отдельное приложение с публичным API, закрытыми внутренними endpoints, HTTPS, очередью задач, базой данных, vector store, секретами в `.env`, healthcheck, логами, мониторингом, резервным копированием и понятным откатом.
В результате будет рабочий контур:
- сервер описан в `server_inventory`;
- домен и DNS записаны в `domain_config`;
- пользователь Linux описан в `deploy_user`;
- код лежит в `/opt/ai-agent`;
- секреты лежат в `.env.production`;
- приложение упаковано в Docker image;
- сервисы описаны в `docker-compose.yml`;
- web API агента слушает только внутренний порт;
- Nginx принимает публичный HTTPS;
- `/health` проверяет готовность сервиса;
- Redis хранит очередь задач;
- worker выполняет долгие agent runs;
- Postgres хранит состояние агента;
- Qdrant или другой vector store хранит embeddings;
- tool policy ограничивает действия агента;
- логи пишутся в `agent_run_log`;
- ошибки пишутся в `agent_error_log`;
- метрики пишутся в `agent_metrics`;
- backup сохраняет базу и конфиги;
- rollback возвращает предыдущую версию.
Первая версия должна уметь принимать webhook или API-запрос, создавать задачу, выполнять agent run в worker, отдавать результат, логировать ошибки и безопасно переживать перезапуск сервера.
Что понадобится
Минимальный набор:
- VPS на Ubuntu 22.04 или 24.04;
- домен или поддомен, например `agent.example.com`;
- SSH-доступ к серверу;
- отдельный deploy-пользователь;
- Docker и Docker Compose;
- Nginx или Caddy;
- TLS-сертификат через Let's Encrypt;
- Git-репозиторий с кодом агента;
- LLM API key или доступ к локальной модели;
- Postgres для состояния;
- Redis для очереди;
- Qdrant, Chroma или другой vector store, если нужен RAG;
- `.env.production` с секретами;
- тестовый запрос для проверки;
- список tools, которые агенту разрешено вызывать.
Для MVP не нужен Kubernetes. Docker Compose достаточно, если один сервер, понятные лимиты и есть ручной rollback.
Шаг 1. Зафиксируйте целевую архитектуру
Не начинайте с установки пакетов. Сначала опишите, что именно будет работать на сервере.
Минимальная схема:
client_or_webhook
-> nginx_https
-> agent_api
-> redis_queue
-> agent_worker
-> postgres
-> vector_store
-> llm_provider
Создайте `deployment_architecture`:
id
component_key
component_type
public_access
internal_port
depends_on
healthcheck_url
is_required
Заполните компоненты:
- `nginx_https` - public reverse proxy;
- `agent_api` - private API;
- `agent_worker` - background worker;
- `postgres` - state database;
- `redis` - queue;
- `qdrant` - vector store;
- `backup_job` - scheduled backup;
- `monitoring` - health and metrics.
Проверка: публичным должен быть только HTTPS-вход, внутренние порты не должны торчать наружу.
Шаг 2. Подберите сервер
Создайте `server_inventory`.
Колонки:
id
hostname
provider
region
cpu_cores
ram_gb
disk_gb
os_version
public_ip
private_ip
purpose
created_at
Для обычного агента с облачной LLM берите:
- 2 CPU;
- 4 GB RAM;
- 40 GB SSD;
- Ubuntu 22.04 или 24.04;
- swap 2-4 GB;
- ежедневный snapshot у провайдера.
Для агента с локальной LLM требования выше:
- 8-16 CPU;
- 32-64 GB RAM;
- GPU, если модель должна отвечать быстро;
- 100-500 GB SSD под модели и индексы.
Проверка: сервер должен выдерживать не только web API, но и worker, Redis, Postgres, vector store и логи.
Шаг 3. Настройте DNS
Создайте `domain_config`.
Колонки:
id
domain
record_type
record_name
record_value
ttl
is_active
checked_at
Для поддомена:
record_type: A
record_name: agent
record_value: SERVER_PUBLIC_IP
ttl: 300
Проверьте DNS:
dig +short agent.example.com
Ожидаемый результат:
SERVER_PUBLIC_IP
Проверка: домен резолвится на IP сервера до настройки HTTPS.
Шаг 4. Создайте deploy-пользователя
Не запускайте агента от `root`.
Команды:
adduser deploy
usermod -aG sudo deploy
usermod -aG docker deploy
Создайте `deploy_user`:
id
username
home_dir
ssh_key_fingerprint
sudo_allowed
docker_allowed
created_at
Правила:
- вход по SSH-ключу;
- парольный SSH выключен после проверки;
- root login выключен после проверки;
- права на проект принадлежат `deploy`;
- `.env.production` читается только владельцем.
Проверка: `deploy` может выполнить `docker compose ps`, но приложение не работает от `root`.
Шаг 5. Обновите сервер и поставьте базовые пакеты
Под пользователем с sudo выполните:
sudo apt update
sudo apt upgrade -y
sudo apt install -y ca-certificates curl git ufw fail2ban htop jq unzip
Включите firewall:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
Проверка: снаружи доступны только `22`, `80`, `443`, а порты `8000`, `5432`, `6379`, `6333` закрыты.
Шаг 6. Установите Docker и Compose
Команды:
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker deploy
docker --version
docker compose version
Перезайдите по SSH, чтобы группа `docker` применилась.
Проверка:
docker run --rm hello-world
Ожидаемый результат: Docker скачивает тестовый image и завершает контейнер без ошибки.
Шаг 7. Создайте структуру проекта
Создайте директории:
sudo mkdir -p /opt/ai-agent
sudo chown -R deploy:deploy /opt/ai-agent
cd /opt/ai-agent
mkdir -p app data/postgres data/redis data/qdrant logs backups releases scripts nginx
Структура:
/opt/ai-agent
app
data
postgres
redis
qdrant
logs
backups
releases
scripts
nginx
Создайте `deployment_paths`:
id
path_key
absolute_path
owner
permissions
backup_required
Проверка: `deploy` может писать в `/opt/ai-agent/logs`, но `.env.production` не читается чужими пользователями.
Шаг 8. Скопируйте код агента
Вариант через Git:
cd /opt/ai-agent/app
git clone git@github.com:company/ai-agent.git .
git checkout main
Вариант через архив:
cd /opt/ai-agent/app
unzip ai-agent-release.zip
Создайте `release_registry`:
id
release_id
git_sha
branch
image_tag
deployed_by
deployed_at
status
Первый release:
release_id: 2026-05-23-001
branch: main
status: prepared
Проверка: на сервере есть код, а `git rev-parse --short HEAD` показывает конкретный commit.
Шаг 9. Подготовьте переменные окружения
Создайте `/opt/ai-agent/.env.production`.
Пример:
APP_ENV=production
APP_PORT=8000
PUBLIC_BASE_URL=https://agent.example.com
DATABASE_URL=postgresql://agent_user:CHANGE_ME@postgres:5432/agent_db
REDIS_URL=redis://redis:6379/0
VECTOR_STORE_URL=http://qdrant:6333
LLM_PROVIDER=openai
LLM_MODEL=gpt-4.1-mini
LLM_API_KEY=CHANGE_ME
AGENT_MAX_STEPS=8
AGENT_TIMEOUT_SECONDS=90
AGENT_DAILY_BUDGET_USD=20
AGENT_ENABLE_WRITE_TOOLS=false
AGENT_ENABLE_WEB_SEARCH=false
LOG_LEVEL=info
SENTRY_DSN=
Права:
chmod 600 /opt/ai-agent/.env.production
Создайте `secret_registry`:
id
secret_key
storage_place
rotation_required
last_rotated_at
owner
Проверка: `.env.production` не попадает в Git и не выводится в логи.
Шаг 10. Опишите состояние агента в базе
Создайте таблицы для production-состояния.
`agent_runs`:
id
run_id
request_id
user_id
status
input_json
output_json
error_message
started_at
finished_at
created_at
`agent_tasks`:
id
task_id
run_id
task_type
payload_json
status
attempts
next_retry_at
created_at
updated_at
`agent_tool_calls`:
id
run_id
tool_name
input_json
output_json
status
duration_ms
created_at
`agent_run_log`:
id
run_id
level
message
context_json
created_at
Проверка: после тестового запуска в базе виден run, task, tool calls и финальный статус.
Шаг 11. Напишите Dockerfile
Пример для Python/FastAPI-агента:
FROM python:3.12-slim
WORKDIR /app
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Если агент на Node.js:
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 8000
CMD ["npm", "run", "start"]
Проверка: image собирается локально на сервере командой `docker build -t ai-agent:local .`.
Шаг 12. Создайте `docker-compose.yml`
Файл `/opt/ai-agent/docker-compose.yml`:
services:
agent_api:
build:
context: ./app
image: ai-agent:production
env_file:
- .env.production
command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
expose:
- "8000"
depends_on:
- postgres
- redis
- qdrant
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:8000/health"]
interval: 30s
timeout: 5s
retries: 3
agent_worker:
image: ai-agent:production
env_file:
- .env.production
command: ["python", "-m", "worker"]
depends_on:
- postgres
- redis
- qdrant
restart: unless-stopped
postgres:
image: postgres:16
environment:
POSTGRES_DB: agent_db
POSTGRES_USER: agent_user
POSTGRES_PASSWORD: CHANGE_ME
volumes:
- ./data/postgres:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes"]
volumes:
- ./data/redis:/data
restart: unless-stopped
qdrant:
image: qdrant/qdrant:latest
volumes:
- ./data/qdrant:/qdrant/storage
restart: unless-stopped
В production замените `CHANGE_ME` на пароль из `.env.production` или используйте Docker secrets.
Проверка:
cd /opt/ai-agent
docker compose config
Команда должна показать итоговый compose без ошибок.
Шаг 13. Сделайте endpoint `/health`
`/health` не должен вызывать LLM. Он должен быстро проверять базовые зависимости.
Ответ:
{
"status": "ok",
"app": "agent_api",
"db": "ok",
"redis": "ok",
"vector_store": "ok",
"version": "2026-05-23-001"
}
Правила:
- timeout до 2 секунд;
- без секретов;
- без проверки дорогих LLM-запросов;
- статус `degraded`, если vector store недоступен;
- статус `fail`, если база или Redis недоступны.
Проверка:
curl -fsS http://localhost:8000/health
Ожидаемый результат: JSON со статусом `ok`.
Шаг 14. Запустите сервисы первый раз
Команды:
cd /opt/ai-agent
docker compose build
docker compose up -d
docker compose ps
Проверьте логи:
docker compose logs --tail=100 agent_api
docker compose logs --tail=100 agent_worker
Создайте `deployment_events`:
id
release_id
event_type
status
message
created_at
Проверка: `agent_api`, `agent_worker`, `postgres`, `redis`, `qdrant` находятся в статусе running или healthy.
Шаг 15. Настройте Nginx как reverse proxy
Файл `/opt/ai-agent/nginx/agent.conf`:
server {
listen 80;
server_name agent.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 120s;
}
}
Если Nginx стоит на хосте, добавьте upstream на опубликованный порт. Если Nginx в Docker, добавьте его отдельным сервисом и прокидывайте только `80` и `443`.
Проверка:
sudo nginx -t
sudo systemctl reload nginx
curl -I http://agent.example.com/health
Ожидаемый результат: HTTP-ответ от агента через домен.
Шаг 16. Включите HTTPS
Через Certbot:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d agent.example.com
Проверьте автообновление:
sudo certbot renew --dry-run
Создайте `tls_certificate`:
id
domain
issuer
expires_at
auto_renew_enabled
checked_at
Проверка:
curl -I https://agent.example.com/health
Ожидаемый результат: `200` или `204`, сертификат валидный, редирект с HTTP на HTTPS работает.
Шаг 17. Закройте внутренние endpoints
Публичными могут быть только:
- `/health`;
- `/webhook/...`, если нужен входящий webhook;
- `/api/run`, если есть авторизация;
- `/api/result/...`, если есть авторизация.
Закрытыми должны быть:
- `/debug`;
- `/metrics`, если нет basic auth или allowlist;
- `/admin`;
- `/queue`;
- `/tools`;
- `/internal`;
- `/docs`, если там видны схемы приватного API.
Создайте `endpoint_policy`:
id
path_pattern
public_access
auth_required
allowed_methods
rate_limit_key
is_active
Проверка: запрос к `/internal/tools` снаружи возвращает `403` или `404`.
Шаг 18. Добавьте авторизацию API
Для MVP можно начать с API key.
Заголовок:
Authorization: Bearer YOUR_AGENT_API_KEY
Создайте `api_clients`:
id
client_key
name
api_key_hash
allowed_scopes_json
rate_limit_per_minute
is_active
created_at
Scopes:
- `agent.run`;
- `agent.result.read`;
- `webhook.receive`;
- `admin.read`;
- `admin.write`.
Проверка: запрос без token получает `401`, запрос с неправильным token получает `403`.
Шаг 19. Настройте входящий API-запрос
Endpoint `POST /api/run` должен принимать понятный JSON.
Пример:
{
"request_id": "req-001",
"user_id": "u-123",
"task_type": "answer_question",
"input": {
"question": "Как подключить агента к Telegram?",
"context": "Пользователь на тарифе Pro"
}
}
Ответ API:
{
"run_id": "run-001",
"status": "queued"
}
Правила:
- API не выполняет долгий agent run синхронно;
- API кладет задачу в очередь;
- worker забирает задачу;
- результат можно получить по `GET /api/runs/{run_id}`;
- каждый запрос имеет `request_id` для идемпотентности.
Проверка: повторный запрос с тем же `request_id` не создает дубль run.
Шаг 20. Настройте очередь задач
Создайте `queue_config`.
Колонки:
id
queue_name
worker_count
max_retries
timeout_seconds
dead_letter_enabled
is_active
Очереди:
- `agent_runs` - обычные задачи;
- `agent_long_runs` - долгие задачи;
- `embeddings` - индексация документов;
- `webhooks` - входящие webhook;
- `dead_letter` - задачи после ошибок.
Правила:
- timeout agent run: 90-180 секунд;
- retries: 2-3;
- exponential backoff;
- dead letter после последней ошибки;
- отдельная очередь для embeddings, чтобы они не блокировали ответы.
Проверка: если LLM API временно недоступен, задача повторяется, а не теряется.
Шаг 21. Настройте worker
Worker должен выполнять задачи отдельно от web API.
Минимальная логика:
- взять задачу из Redis;
- создать запись в `agent_runs`;
- загрузить policy;
- собрать prompt;
- вызвать LLM;
- вызвать разрешенные tools;
- сохранить результат;
- обновить статус;
- записать логи;
- отправить webhook о завершении, если нужен.
Статусы run:
- `queued`;
- `running`;
- `waiting_tool`;
- `completed`;
- `failed`;
- `cancelled`;
- `timeout`.
Проверка: остановите worker на минуту, создайте задачу, включите worker и убедитесь, что задача обработалась.
Шаг 22. Подключите Postgres
Проверьте подключение из контейнера:
docker compose exec agent_api python - <<'PY'
import os
print(os.environ["DATABASE_URL"])
PY
Миграции запускайте отдельной командой:
docker compose exec agent_api python -m app.migrate
Создайте `database_migrations`:
id
migration_name
batch
status
executed_at
Правила:
- миграции запускаются до переключения трафика;
- destructive migrations не делаются без backup;
- rollback миграций проверяется отдельно;
- индексы добавляются на `run_id`, `request_id`, `status`, `created_at`;
- большие таблицы логов чистятся по retention policy.
Проверка: приложение стартует после миграций, а старые runs читаются.
Шаг 23. Подключите vector store
Если агент использует RAG, поднимите Qdrant или подключите внешний vector DB.
Коллекция:
collection_name: agent_knowledge
vector_size: зависит от embedding-модели
distance: cosine
Создайте `vector_collections`:
id
collection_name
embedding_model
vector_size
distance
documents_count
last_indexed_at
Правила:
- embeddings пересоздаются при смене embedding-модели;
- chunks имеют `source_url`;
- удаленные документы выключаются через `is_active`;
- индексация идет отдельной очередью;
- API агента не должен падать, если идет reindex.
Проверка: тестовый вопрос находит chunk из базы знаний и возвращает ссылку на источник.
Шаг 24. Ограничьте tools
Создайте `tool_policy`.
Колонки:
id
tool_name
enabled
requires_approval
allowed_scopes_json
blocked_inputs_json
max_calls_per_run
timeout_seconds
Правила для первого запуска:
- `search_knowledge_base` включен;
- `read_customer_profile` только read-only;
- `send_message` выключен или требует approval;
- `write_to_crm` выключен;
- `delete_record` выключен;
- `refund_payment` выключен;
- `web_search` выключен, если не нужен;
- каждый tool имеет timeout;
- каждый tool пишет лог.
Проверка: агент не может выполнить write-действие без явного разрешения.
Шаг 25. Добавьте rate limit
Создайте `rate_limit_rules`.
Колонки:
id
scope
limit_per_minute
limit_per_day
burst
action_on_limit
is_active
Стартовые лимиты:
- `api_client`: 60 запросов в минуту;
- `user`: 20 запусков в минуту;
- `agent_run`: 8 LLM calls на run;
- `tool_call`: 20 tool calls на run;
- `daily_budget`: лимит расходов в день.
Проверка: серия из 100 запросов за минуту получает `429`, а сервер не ложится.
Шаг 26. Настройте бюджет LLM
Создайте `llm_usage_log`.
Колонки:
id
run_id
provider
model
input_tokens
output_tokens
estimated_cost_usd
created_at
Создайте `budget_policy`:
id
scope
daily_limit_usd
monthly_limit_usd
action_on_limit
is_active
Правила:
- записывать tokens после каждого LLM call;
- останавливать новые runs при превышении дневного лимита;
- показывать понятную ошибку вместо падения;
- использовать дешевую модель для классификации;
- дорогую модель включать только для сложных задач.
Проверка: тестовый лимит `0.01` останавливает новые дорогие запросы.
Шаг 27. Настройте логи
Создайте `agent_error_log`.
Колонки:
id
run_id
error_type
error_message
stack_hash
context_json
created_at
Логируйте:
- старт run;
- завершение run;
- LLM request без секретов;
- LLM error;
- tool call;
- tool error;
- timeout;
- retry;
- rate limit;
- guardrail block.
В Docker смотрите:
docker compose logs --tail=200 agent_api
docker compose logs --tail=200 agent_worker
Проверка: ошибка LLM API видна в логах, но API key там не появляется.
Шаг 28. Настройте метрики
Создайте `agent_metrics`.
Колонки:
id
metric_date
total_runs
completed_runs
failed_runs
timeout_runs
avg_latency_ms
p95_latency_ms
total_cost_usd
tool_errors
created_at
Смотрите:
- процент ошибок;
- p95 latency;
- среднюю стоимость run;
- количество timeout;
- длину очереди;
- количество retries;
- частоту guardrails;
- нагрузку CPU/RAM/disk.
Проверка: после 10 тестовых runs метрики заполняются и показывают не нули.
Шаг 29. Добавьте алерты
Создайте `alert_rules`.
Колонки:
id
rule_key
condition
severity
target_channel
is_active
Первый набор:
- `/health` недоступен 2 минуты;
- error rate выше 10%;
- очередь больше 100 задач;
- disk usage выше 80%;
- дневной LLM budget выше 80%;
- Postgres недоступен;
- Redis недоступен;
- сертификат истекает меньше чем через 14 дней.
Проверка: временно остановите `agent_api` и убедитесь, что alert создается.
Шаг 30. Настройте backup
Создайте `/opt/ai-agent/scripts/backup.sh`.
#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR="/opt/ai-agent/backups/$(date +%Y-%m-%d_%H-%M-%S)"
mkdir -p "$BACKUP_DIR"
docker compose exec -T postgres pg_dump -U agent_user agent_db > "$BACKUP_DIR/postgres.sql"
tar -czf "$BACKUP_DIR/qdrant.tar.gz" -C /opt/ai-agent/data qdrant
cp /opt/ai-agent/.env.production "$BACKUP_DIR/env.production.copy"
Права:
chmod 700 /opt/ai-agent/scripts/backup.sh
Создайте `backup_runs`:
id
backup_id
status
backup_path
size_mb
started_at
finished_at
Проверка: backup создается, а восстановление проверено на тестовой папке или staging-сервере.
Шаг 31. Настройте log rotation
Если логи пишутся в файлы, создайте `/etc/logrotate.d/ai-agent`.
/opt/ai-agent/logs/*.log {
daily
rotate 14
compress
missingok
notifempty
copytruncate
}
Если логи только Docker:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "5"
}
}
Проверка: логи не растут бесконечно и не забивают диск.
Шаг 32. Подготовьте rollback
Создайте `rollback_plan`.
Колонки:
id
release_id
previous_release_id
image_tag
db_backup_id
rollback_command
tested_at
Простой rollback через image tag:
cd /opt/ai-agent
docker compose pull
docker compose up -d
Более понятный вариант:
docker tag ai-agent:previous ai-agent:production
docker compose up -d agent_api agent_worker
Правила:
- храните предыдущий image;
- храните backup базы до миграций;
- не удаляйте старый `.env.production`;
- проверяйте `/health` после rollback;
- фиксируйте rollback в `deployment_events`.
Проверка: на staging выполните rollback до предыдущей версии и убедитесь, что API отвечает.
Шаг 33. Создайте deploy-скрипт
Файл `/opt/ai-agent/scripts/deploy.sh`:
#!/usr/bin/env bash
set -euo pipefail
cd /opt/ai-agent/app
git fetch origin
git checkout main
git pull --ff-only
cd /opt/ai-agent
./scripts/backup.sh
docker compose build agent_api
docker compose up -d
docker compose ps
curl -fsS https://agent.example.com/health
Права:
chmod 700 /opt/ai-agent/scripts/deploy.sh
Проверка: deploy-скрипт либо завершается успешно, либо падает до переключения на нерабочее состояние.
Шаг 34. Проверьте безопасность секретов
Проверки:
grep -R "LLM_API_KEY" /opt/ai-agent/logs || true
find /opt/ai-agent -name ".env*" -ls
ls -la /opt/ai-agent/.env.production
Правила:
- API keys не в Git;
- API keys не в Dockerfile;
- API keys не в логах;
- `.env.production` имеет права `600`;
- backup с `.env` хранится отдельно и защищенно;
- при утечке ключ можно быстро заменить;
- debug mode выключен в production.
Проверка: ни один публичный endpoint не возвращает env, stack trace или конфиг.
Шаг 35. Проверьте сетевую поверхность
На сервере:
sudo ss -tulpn
sudo ufw status numbered
Снаружи:
nmap -Pn agent.example.com
Ожидаемо открыты:
- `80`;
- `443`;
- `22`, если SSH не вынесен на другой порт или не закрыт allowlist.
Не должны быть открыты:
- `5432`;
- `6379`;
- `6333`;
- `8000`;
- внутренние admin ports.
Проверка: Postgres, Redis и vector store недоступны из интернета.
Шаг 36. Сделайте тестовый запуск агента
Отправьте тестовый запрос:
curl -sS https://agent.example.com/api/run \
-H "Authorization: Bearer YOUR_AGENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"request_id": "test-001",
"user_id": "test-user",
"task_type": "answer_question",
"input": {
"question": "Составь короткий ответ клиенту о статусе заявки"
}
}'
Проверьте:
- API вернул `run_id`;
- task появилась в Redis;
- worker взял task;
- run перешел в `running`;
- LLM вызван один раз;
- result записан в Postgres;
- run перешел в `completed`;
- логи не содержат секретов;
- стоимость записана;
- `/api/runs/{run_id}` возвращает результат.
Проверка: весь путь от API до результата работает без ручного запуска команд.
Шаг 37. Проверьте отказоустойчивость
Сделайте три теста.
Остановите worker:
docker compose stop agent_worker
Создайте задачу, затем включите worker:
docker compose start agent_worker
Остановите Redis:
docker compose stop redis
Проверьте `/health`.
Остановите LLM-доступ, например временно подставьте неверный ключ на staging.
Ожидаемые реакции:
- без worker задачи ждут в очереди;
- без Redis `/health` становится `fail`;
- при ошибке LLM задача получает retry;
- после max retries задача уходит в dead letter;
- API не раскрывает stack trace клиенту.
Проверка: агент деградирует управляемо, а не ломается молча.
Шаг 38. Настройте systemd для compose
Чтобы Docker Compose поднимался после перезагрузки, создайте unit.
Файл `/etc/systemd/system/ai-agent.service`:
[Unit]
Description=AI Agent Docker Compose
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/ai-agent
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
Команды:
sudo systemctl daemon-reload
sudo systemctl enable ai-agent
sudo systemctl start ai-agent
sudo systemctl status ai-agent
Проверка: после `sudo reboot` сервисы снова поднимаются.
Шаг 39. Настройте staging перед production
Если агент будет работать с клиентами, сделайте staging.
Отличия staging:
- отдельный домен `agent-staging.example.com`;
- отдельная база;
- отдельные API keys;
- маленький LLM budget;
- тестовые tools;
- fake webhook;
- отключенные write-действия;
- тестовая база знаний.
Создайте `environment_registry`:
id
env_key
base_url
database_name
llm_budget_usd
write_tools_enabled
created_at
Проверка: staging не может случайно отправить сообщение реальному клиенту.
Шаг 40. Минимальный результат для запуска
MVP готов, если выполнены условия:
- домен указывает на сервер;
- HTTPS работает;
- Docker Compose поднимает все сервисы;
- `/health` возвращает `ok`;
- API требует авторизацию;
- внутренние endpoints закрыты;
- задача создается через `/api/run`;
- worker выполняет задачу;
- результат сохраняется;
- logs и error logs пишутся;
- Postgres и Redis не доступны из интернета;
- vector store работает, если нужен RAG;
- tool policy запрещает опасные действия;
- rate limit возвращает `429`;
- backup создается;
- rollback проверен;
- сервисы стартуют после reboot;
- LLM budget ограничен;
- alert приходит при падении `/health`;
- секреты не попадают в логи.
Финальная проверка: перезагрузите сервер, дождитесь запуска, отправьте тестовый `/api/run`, получите результат, проверьте логи, метрики и backup. Если все проходит без ручного запуска worker, агент готов к ограниченному production-трафику.
Что нельзя автоматизировать в первой версии
В первой версии не автоматизируйте:
- самостоятельное изменение production-конфига агентом;
- выдачу новых API keys агентом;
- удаление данных из Postgres;
- удаление vector collection;
- изменение DNS;
- изменение firewall;
- запуск shell-команд по просьбе пользователя;
- write-tools без approval;
- оплату, возвраты и финансовые операции;
- auto-deploy без тестов;
- auto-rollback без понятного условия;
- чтение `.env.production` через tool;
- публичный доступ к debug endpoints;
- обучение на production-логах без очистки данных;
- хранение персональных данных без retention policy.
Сначала сервер должен стабильно принимать задачи, выполнять их в worker, писать логи и безопасно ограничивать инструменты. Расширяйте автоматизацию только после тестов и мониторинга.
Частые вопросы
Можно ли запускать ИИ-агента без Docker?
Можно, через systemd и виртуальное окружение, но Docker Compose проще для повторяемого запуска: отдельно web API, worker, Redis, Postgres и vector store.
Нужно ли сразу использовать Kubernetes?
Нет. Для одного сервера и первого production MVP Docker Compose обычно достаточно. Kubernetes имеет смысл, когда нужны несколько серверов, autoscaling, сложная сеть и отдельная команда эксплуатации.
Где хранить ключи от LLM API?
В `.env.production`, secret manager или Docker secrets. Нельзя хранить ключи в Git, Dockerfile, публичных логах, prompt-текстах и админских debug endpoints.
Что делать, если агент начал ошибаться после релиза?
Остановите auto-send или write-tools, откатите image на предыдущий tag, проверьте `agent_error_log`, сравните prompts и tools, затем прогоните тестовые runs на staging.
Как понять, что сервер готов к реальным пользователям?
Сервер готов, если проходит полный тест: HTTPS, auth, `/health`, queue, worker, Postgres, vector store, логи, rate limit, backup, rollback, restart после reboot и отсутствие открытых внутренних портов.