Справочник3 сентября 2026 г.·обновлено 3 сентября 2026 г.

Разработка ИИ-агентов: цикл, инструменты, память, контроль

Из чего физически собирается агент: цикл вызовов, схемы инструментов, три слоя памяти и ограничители, без которых он уходит в разнос.

Что это решает

Разработка ИИ-агентов начинается там, где чат перестаёт помогать: данные лежат в базе, действие выполняется в чужом API, а результат надо проверить и записать. В переписке с моделью человек работает шиной передачи — выгрузил, вставил, забрал ответ, руками применил. Агент замыкает круг сам: ходит за данными, вызывает операцию, повторяет шаг после ошибки и останавливается, когда задача закрыта. Плата — новая инженерная работа: описать инструменты, поставить ограничители, научиться читать журнал шагов.

Как устроено

Агент собирается из четырёх частей: цикл, инструменты, память, контроль. Уберите любую — получится либо болтливый чат, либо неуправляемый скрипт.

Цикл

Ядро живёт в коде оркестратора и выглядит как обычный while:

  1. Собрать запрос: системная инструкция, история, новый вход, описание доступных инструментов.
  2. Отправить в модель.
  3. Разобрать ответ. Модель вернёт либо финальный текст, либо структурированный запрос на вызов — tool_calls с именем функции и аргументами в JSON.
  4. Оркестратор исполняет вызов своим кодом и кладёт результат обратно в историю отдельным сообщением с ролью tool.
  5. Вернуться к шагу 2 — пока не придёт финальный текст или пока не сработает ограничитель.

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

Инструменты

Каждый инструмент описывается тремя полями: name, description, parameters (JSON Schema). Модель выбирает по описанию, поэтому описание пишется для читателя, который кроме него ничего не видит: что делает, когда применять, чего не делает, что вернёт.

Правила, которые экономят потом дни отладки:

  • Одно действие — один инструмент. Универсальный do_everything с полем action внутри превращает выбор в угадывание.
  • Обязательных параметров минимум, у остальных — значения по умолчанию. Каждое обязательное поле повышает шанс, что модель придумает его содержимое.
  • Ответ структурированный: статус, данные, и текст ошибки, по которому можно исправиться. Ошибка 500 не лечится, период задан наоборот: date_from позже date_to — лечится на следующем шаге.
  • Чтение и запись разделены на уровне имени: get_orders и create_order никогда не живут в одной функции.
  • Пагинация и лимиты внутри инструмента, а не в голове модели. Инструмент, способный вернуть десятки тысяч строк, забьёт контекст с первого вызова.

Второй путь — MCP: инструмент описывается один раз на стороне сервера и подключается к любому совместимому клиенту без переписывания адаптеров под каждый рантайм.

Память

Длинная история и память — разные вещи. Слоёв три.

СлойГде живётЧто попадаетКогда чистится
Контекст шагаокно моделисистемная инструкция, последние сообщения, результаты вызововпри переполнении, вытеснением старого
Рабочая памятьфайл или таблица задачиплан, что уже сделано, промежуточные выводыпо завершении задачи
ДолговременнаяБД, векторный индекс, репозиторий заметокправила домена, факты, прошлые решениявручную, ревизией

Типичная ошибка — тащить в каждый шаг всю переписку целиком. Контекст забивается сырыми выгрузками, модель начинает отвечать по началу диалога и терять свежие факты. Рабочий приём: результат тяжёлого вызова сохранить в файл, в историю положить короткую сводку и путь к файлу, а сам файл читать инструментом по требованию.

Долговременная память ценна не объёмом, а тем, что в неё попадают правила. Разобранный сбой заканчивается строчкой в инструкции агента, иначе тот же сбой повторится на следующей неделе.

Контроль

Ограничители ставятся в коде оркестратора, не в промпте. Промпт — рекомендация, код — граница.

  • Белый список инструментов на роль или на запуск.
  • Подтверждение человека для всего, что пишет наружу.
  • max_steps и таймаут на задачу. Без них зацикливание съедает бюджет молча.
  • Бюджет токенов с остановкой по достижении.
  • Песочница для исполнения кода и команд.
  • Журнал: номер шага, имя инструмента, аргументы, усечённый результат, длительность, стоимость.
  • Идемпотентность записи: ключ операции, чтобы повтор после таймаута не создал дубль.

Правило: модель только предлагает вызов, исполняет его код, а право на запись выдаётся списком, а не доверием.

Как подключить

Шаг 1. Выбрать одну задачу с проверяемым результатом. «Помогать с аналитикой» не проверяется. «По названию компании найти её договоры и вернуть даты окончания» — проверяется на десятке примеров.

Шаг 2. Описать инструменты. Начните с двух-трёх, только чтение. Схема выглядит так:

{
  "type": "function",
  "function": {
    "name": "get_orders",
    "description": "Вернуть заказы клиента за период. Только чтение. Максимум 200 строк, дальше — cursor.",
    "parameters": {
      "type": "object",
      "properties": {
        "client_id": {"type": "integer"},
        "date_from": {"type": "string", "format": "date"},
        "date_to": {"type": "string", "format": "date"},
        "cursor": {"type": "string"}
      },
      "required": ["client_id"]
    }
  }
}

Шаг 3. Написать цикл. Каркас на любом языке одинаковый:

messages = [{"role": "system", "content": SYSTEM}, {"role": "user", "content": task}]
for step in range(MAX_STEPS):
    resp = client.chat(messages=messages, tools=TOOLS)
    msg = resp.choices[0].message
    messages.append(msg)
    if not msg.tool_calls:
        return msg.content
    for call in msg.tool_calls:
        result = registry[call.function.name](json.loads(call.function.arguments))
        log(step, call.function.name, call.function.arguments, result)
        messages.append({"role": "tool", "tool_call_id": call.id,
                         "content": json.dumps(result, ensure_ascii=False)[:MAX_TOOL_CHARS]})
raise StepLimit()

Обрезка результата (MAX_TOOL_CHARS) обязательна с первого дня, иначе один неудачный вызов положит окно.

Шаг 4. Системная инструкция. Четыре блока: роль и предметная область; что запрещено (какие инструменты не трогать, что не выдумывать); формат финального ответа; критерий завершения — по какому признаку задача считается закрытой.

Шаг 5. Журнал с первого запуска. Пишите в файл или таблицу, а не в stdout. Разбор любого странного поведения начинается с чтения последовательности вызовов, и без неё остаётся гадание.

Шаг 6. Ограничители. MAX_STEPS, таймаут на инструмент, таймаут на задачу, лимит суммарных токенов, allowlist.

Шаг 7. Золотой набор. Несколько десятков реальных входов с известным правильным исходом, сложенных в файл. Прогон набора — единственный способ увидеть, что правка промпта улучшила поведение, а не переставила ошибки.

Шаг 8. Права на запись. Добавляются последними, по одной операции, с подтверждением и с ключом идемпотентности.

Полезные сценарии

  • Разбор входящей почты: классифицировать письмо, вытащить реквизиты, завести карточку в трекере.
  • Дежурный по мониторингу: собрать ошибки за ночь, сгруппировать по причине, отправить сводку с ссылками.
  • Сверка данных между двумя системами: найти расхождения и вернуть список пар с пояснением, без записи.
  • Подготовка регулярного отчёта: сходить в базу и в рекламный кабинет, собрать цифры, оформить по шаблону.
  • Первая линия поддержки: найти ответ в базе знаний, ответить, эскалировать при неуверенности.
  • Рутина в трекере: перенести задачи по правилам, проставить метки, собрать список зависших.

Ограничения

Задача с одним детерминированным ответом дешевле решается скриптом: если правило записывается в SQL или в двадцать строк кода, агент добавит только недетерминированность и счёт за токены.

Жёсткая латентность плохо совместима с циклом: каждый шаг — сетевой вызов модели плюс исполнение инструмента, и число шагов заранее неизвестно.

Отладка отличается от обычной: одинаковый вход даёт разные траектории. Тесты пишутся на исход и на инварианты (не более N шагов, ни одного вызова из чёрного списка, схема ответа валидна), а не на точный текст.

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

Ответственность не делегируется. Всё, что агент делает наружу — письма, платежи, публикации, удаление, — остаётся на владельце процесса, и это диктует, где стоит подтверждение.

Как проверить результат

Прогнать золотой набор и посмотреть на пять чисел из журнала:

  1. Доля задач, дошедших до финального ответа без исчерпания лимита шагов.
  2. Доля правильных исходов при ручной сверке с эталоном.
  3. Среднее и максимальное число шагов. Всплеск максимума — признак зацикливания.
  4. Доля вызовов, отвергнутых валидацией схемы. Высокая — описание параметров неоднозначно.
  5. Повторы одного инструмента с одинаковыми аргументами подряд — модель не поняла результат, чинится текстом ответа инструмента.

Отдельно проверить ограничители: подсунуть заведомо неразрешимую задачу и убедиться, что цикл останавливается по max_steps и пишет причину, а не крутится до исчерпания бюджета. Затем убрать один инструмент из allowlist и убедиться, что попытка вызова заканчивается отказом в коде, а не выполнением.

  • ии-агенты
  • архитектура
  • инструменты
  • память