ИИ-агент на VPS обычно означает программу, которая получает задачи из Telegram, веб-формы или расписания, обращается к языковой модели через API, при необходимости вызывает инструменты (поиск, работа с файлами, запросы к вашим сервисам) и возвращает результат. Сам сервер в такой схеме почти ничего не вычисляет: тяжелую работу делает модель у провайдера API. Поэтому запуск агента на VPS - задача про надежность, безопасность и контроль расходов, а не про мощное железо.
Ниже требования к серверу, подготовка окружения, безопасное хранение ключа, минимальный код агента, запуск через systemd, логи, ограничение расходов и правила безопасности.
Какой VPS нужен ИИ-агенту
Если агент вызывает модель через API, ресурсы сервера уходят на сам процесс агента, сетевые запросы и инструменты. Для одного агента без тяжелых задач достаточно 1 vCPU и 1–2 ГБ памяти. Тариф Micro (2 vCPU, 2 ГБ RAM, 20 ГБ диска) подходит для старта. Если рядом работают база данных, n8n или несколько агентов, комфортнее тариф Start с 4 ГБ памяти.
Важно: на небольшом VPS не запускают локальную языковую модель. Даже сжатая модель среднего размера требует нескольких гигабайт памяти только под веса, а при длинном контексте потребность растет из-за кеша внимания. Без GPU генерация идет медленно, и для агента это обычно неприемлемо. Локальные модели запускают на отдельном сервере с большим объемом RAM или с видеокартой. Для агента, который работает через API, обычного VPS достаточно.
- Linux-сервер с Python 3.10 или новее;
- от 1 vCPU и 1 ГБ RAM для одного агента без тяжелых инструментов;
- от 10 ГБ диска для системы, Python-пакетов и логов;
- доступ по SSH с ключом, см. статью Как подключиться к VPS по SSH;
- исходящий доступ по HTTPS к API провайдера модели.
Подготовка пользователя и каталогов
Агента не нужно запускать от root. Если процесс скомпрометируют, ущерб ограничится правами отдельного пользователя. Создайте системного пользователя и каталог проекта:
sudo apt update && sudo apt install -y python3 python3-venv
sudo useradd --system --home-dir /opt/agent --shell /usr/sbin/nologin agent
sudo mkdir -p /opt/agent/app
sudo chown -R agent:agent /opt/agentВиртуальное окружение и зависимости
Зависимости ставятся в отдельное виртуальное окружение. Так системный Python не засоряется, а версии библиотек фиксируются внутри проекта:
sudo -u agent python3 -m venv /opt/agent/venv
sudo -u agent /opt/agent/venv/bin/pip install --upgrade pip httpx
sudo -u agent /opt/agent/venv/bin/pip freeze | sudo tee /opt/agent/app/requirements.txt > /dev/nullВ файл requirements.txt попадут точные версии. Копируйте его вместе с кодом, чтобы повторить установку на другом сервере.
Ключ API: где хранить и как не потерять
Ключ API - секрет, который дает доступ к платному сервису. Его нельзя писать в код, в git, в переписку и в журналы. Храним ключ в файле окружения, который читает только сервисный пользователь:
sudo install -m 600 -o agent -g agent /dev/null /opt/agent/agent.env
sudo nano /opt/agent/agent.envLLM_API_KEY=your-api-key-here
LLM_API_URL=https://api.provider.example/v1/chat/completions
LLM_MODEL=your-model-name
MAX_TOKENS_PER_REQUEST=512Права 600 означают, что файл читает только владелец. Если ключ попал в переписку, скриншот или репозиторий, считайте его скомпрометированным: отзовите его в консоли провайдера и выпустите новый. Удалять следы из истории git при этом недостаточно.
Минимальный код агента
Ниже минимальный цикл: получить задачу, отправить ее модели, записать результат. Пример рассчитан на OpenAI-совместимый формат запроса. Если ваш провайдер использует другой формат или заголовок авторизации, поправьте функцию ask_model по его документации. Функция next_task здесь заглушка: замените ее чтением очереди, файла или Telegram-бота.
import logging
import os
import sys
import time
import httpx
API_KEY = os.environ["LLM_API_KEY"]
API_URL = os.environ["LLM_API_URL"]
MODEL = os.environ["LLM_MODEL"]
MAX_TOKENS = int(os.environ.get("MAX_TOKENS_PER_REQUEST", "512"))
MAX_RETRIES = 3
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
stream=sys.stdout,
)
log = logging.getLogger("agent")
def ask_model(prompt: str) -> str:
headers = {"Authorization": "Bearer " + API_KEY}
payload = {
"model": MODEL,
"max_tokens": MAX_TOKENS,
"messages": [{"role": "user", "content": prompt}],
}
for attempt in range(1, MAX_RETRIES + 1):
try:
r = httpx.post(API_URL, json=payload, headers=headers, timeout=60)
if r.status_code == 429:
wait = 2 ** attempt
log.warning("rate limited, retry in %s s", wait)
time.sleep(wait)
continue
r.raise_for_status()
return r.json()["choices"][0]["message"]["content"]
except httpx.HTTPError as exc:
log.error("request failed, attempt %s, error %s", attempt, type(exc).__name__)
time.sleep(2 ** attempt)
raise RuntimeError("model request failed after retries")
def next_task():
return None # заглушка: вернуть строку задачи или None
def main() -> None:
while True:
task = next_task()
if task is None:
time.sleep(5)
continue
log.info("task received, length=%d", len(task))
answer = ask_model(task)
log.info("answer received, length=%d", len(answer))
# отправить answer пользователю или записать в очередь
if __name__ == "__main__":
main()Обратите внимание на несколько решений. Ответ модели ограничен параметром max_tokens. Повторы при ошибках растут экспоненциально и ограничены тремя попытками, поэтому агент не уходит в бесконечный цикл. В журнал пишутся длины и типы ошибок, но не сам текст ключа и не заголовки запроса.
Для тестов можно загрузить переменные вручную: set -a; . /opt/agent/agent.env; set +a; и запустить /opt/agent/venv/bin/python /opt/agent/app/agent.py от пользователя agent.
Запуск как сервис systemd
Systemd запускает агента при старте системы, перезапускает его после сбоя и ведет журнал. Создайте unit-файл:
[Unit]
Description=AI agent
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=agent
Group=agent
WorkingDirectory=/opt/agent/app
EnvironmentFile=/opt/agent/agent.env
ExecStart=/opt/agent/venv/bin/python /opt/agent/app/agent.py
Restart=on-failure
RestartSec=10
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/opt/agent
PrivateTmp=true
MemoryMax=512M
[Install]
WantedBy=multi-user.targetsudo nano /etc/systemd/system/ai-agent.service
sudo systemctl daemon-reload
sudo systemctl enable --now ai-agent
sudo systemctl status ai-agentЗначение MemoryMax подберите под свой тариф: на сервере с 1 ГБ памяти лимит 512 МБ оставит запас для системы. Если агент начнет выходить за лимит, systemd его остановит, и это лучше, чем незаметная нагрузка на весь сервер.
Логи и диагностика
Журнал сервиса доступен через journalctl. Он не требует отдельной настройки и сохраняет вывод агента между перезагрузками, если включено постоянное хранение journald:
journalctl -u ai-agent -f
journalctl -u ai-agent --since "1 hour ago"
journalctl -u ai-agent -p err
sudo systemctl restart ai-agentЛогируйте объем запросов, номер попытки, время обработки и тип ошибки. Не логируйте ключи, заголовки Authorization и персональные данные из задач без необходимости. Если в журнале появились ключи или личные данные, исправьте код, ротируйте ключ и очистите журнал.
Контроль расходов и лимиты
Агент, который работает без присмотра, может незаметно потратить бюджет: зациклиться, отправить слишком длинный контекст или много раз повторять неудачный запрос. Защищайтесь на нескольких уровнях:
- лимит ответа через max_tokens в каждом запросе;
- дневной лимит токенов или запросов внутри самого агента, например счетчик в JSON-файле с обнулением раз в сутки;
- ограничение частоты запросов и exponential backoff при ошибках 429;
- последовательная обработка очереди для одного агента, без параллельных запросов без необходимости;
- лимит расходов или уведомления о пороге в консоли провайдера, если такая функция доступна;
- дешевая модель для простых задач и дорогая только для сложных.
Лимиты провайдера и лимиты в коде дополняют друг друга. Провайдерский лимит остановит расход даже при ошибке в агенте, а внутренний счетчик не даст агенту израсходовать дневной бюджет за первый час работы.
Безопасность ключей и самого агента
Агент с доступом к ключам, файлам и внешним сервисам - это привлекательная цель. Базовые правила:
- создавайте отдельный ключ для каждого проекта и отзывайте его, если он мог утечь;
- меняйте ключи по графику и после смены людей, которые имели к ним доступ;
- ограничивайте агента каталогом /opt/agent и не давайте ему права, которые он не использует;
- не выполняйте команды оболочки, предложенные моделью, без песочницы и явного списка разрешенных действий;
- помните о prompt injection: текст из страниц, писем и документов может содержать инструкции для агента, поэтому такие инструкции не должны получать право на опасные действия;
- закройте сервер фаерволом, обновляйте систему и следуйте рекомендациям из статьи Безопасность Linux-сервера.
Готовый ИИ-бот или свой агент
Самостоятельный VPS оправдан, когда нужны собственный код, свои инструменты и полный контроль над логикой агента. Если задача стандартная, а времени на настройку, мониторинг и контроль ключей нет, проще воспользоваться готовым вариантом. В Pulsar для этого есть раздел AI Bot. Для собственного агента подойдет VPS из раздела VPS.
Проверка перед запуском
- Запустите агента вручную от пользователя agent и убедитесь, что модель отвечает.
- Проверьте, что ключ не виден в журналах, в истории команд и в репозитории.
- Перезагрузите сервер и убедитесь, что сервис поднимается сам.
- Отправьте тестовый запрос с небольшим max_tokens и проверьте расход в консоли провайдера.
- Сымитируйте ошибку API, например неверный ключ, и убедитесь, что агент не уходит в цикл быстрых повторов.
Если все пункты пройдены, агент готов к работе. Дальше имеет смысл добавить мониторинг доступности сервиса и периодическую проверку расходов, чтобы ошибка в задаче не превратилась в неожиданный счет.