Недавно участвовал в ERC3 соревновании (создание агента на основе LLM для решения задачек). Хочу поделиться своим опытом и выводами.
Планирование и перепланирование
Большая проблема для агента - накопление контекста. Делаем шаг - делаем messages.append(...). Сложные задачки так не выполнить, не хватит контекстного окна.
Есть разные способы - саммаризация или просто отрезать старые. Но я сразу применил - логику планирования. Любая задача - должна иметь первичный план выполнения. Можно разбить её на шаги. Каждый шаг более-менее независим, поэтому можно выполнять в отдельном контексте. Конечно между шагами должна быть передача ключевой информации (результаты выполнения шага, сжатый).
План - list[PlanSteps]. Обычный линейный перечень шагов. Обычно 3-10 шагов.
Но он не может быть статичный, т.к. среда может не соответствовать нашему изначальному плану. Тогда мы включаем перепланирование. Суть - переписать оставшиеся шаги плана, чтобы они учитывали новую информацию. Это позволяет быть гибкими и подстраиваться под среду.
Еще одна интересная деталь: каждый пункт плана сразу устанавливает input/output variables. Т.е. когда мы выполняем шаг, у нас появляется дополнительный стимул среды - типы данных всех output variables. Если агент захочет финализировать шаг, он обязан этому соответствовать. Если нет - сообщаем агенту, просим уточнить. Тут я первый раз встретил проверку типов в рантайме питона (нетиповая штука), использовал typeguard.check_type (применяется просто, assert typeguard.checktype([1, 2], list[int])).
Для планирования нужен structured output (шаги плана отдельные, там надо всё системно выдать). Я использую модель - openai/gpt-4.1. Модель поумнее (надеюсь) и может отвечать согласно JSON Schema.
Размышления агента (reasoning)
Еще я верю в то, что агентов учили размышлять. И надо этим пользоваться.
Перед написанием кода агент расмышляет (модель - deepseek/deepseek-v3.2). Эти размышления НЕ попадают в messages. Этим я экономлю контекст. Но они очень помогают агенту понять ситуацию и принять правильные решения (написать корректные правильный код).
Агенты и среда
Агент это:
while True:
generate_with_llm() # generate and think
determine_next_action() # code execution or function calling
do_action_get_result() # action and feedback from environment
Агент - всегда LLM модель, которая смотрит на контекст и рашает, что можно сделать в этой ситуации (обычно написать код или выбирает какую функцию запустить). После выполнения действия среда должна ответить. Именно этот ответ среды - самое ценное, он позволяет агенту скорректировать понимания среды и действовать дальше.
Самый тонкий момент - как агент будет взаимодействовать со средой.
Можно просто ему дать python и bash и поставить задачу.
Посмотрев это видео я понял, что именно исполнение кода - это наиболее перспективно. Еще ранее эта идея (просто дать агенту код и запусить while True) была реализована в агентах от Hugginface и в Holosophos Ильи Гусева. Можно посмотреть на cursor, там агенты постоянно исполняют код напрямую.
Code execution (python + linux bash)
Агенты основанные на исполнении кода получаются более общего назначения. Хотя в конкретных задачах будут проигрывать агенту, если он специализируется на какой-то области. Как пример - если мне надо прочитать 600 страниц текста и структурировать информацию из них - я возьму qwen + structured output (даже не агент). И даже не подумаю про code execution.
Но именно способность решать разные задачи - наиболее интересная черта таких агентов.
Агенты, основанные на исполнении кода имеют два критических недостатка:
Чтобы писать нормальный код, модель должна быть умной (qwen 4b сложно себе тут представить)
Агент может выполнять любой код (например,
rm -rf ~). Безопасность повышается тем, что агент в docker контейнере. Хотя все равно сложно себе представить, что кто-то решится запустить его на чувствительных данных.
Самое большое преимущество - не надо адаптировать тулы и писать функции специально для агента. Я могу просто добавить в промт:
У тебя есть доступ к tavily, env уже содержит токен. Если надо ищи в интернете.
Pandas и sklearn установлены, можешь использовать.
А во многих случаях, даже этого не требуется. LLM обычно и так знают про эти и многие другие библиотеки. Иногда лучше нас уже. Поэтому им нужно только железо для выполнения кода и хорошо настроенный цикл (написал код - исполнил - посмотрел что получилось).
Можно дать агенту право на pip install и на запить/чтение файлов.
Можно дать requests, beautiful soup, selenium.
Хотя повторю, пока это возможно только в песочнице со строгим контролем. Отправлять такого агента в самостоятельное плаванье нельзя.
Ответ языковой модели я структурирую примерно так:
<thinking>
тут размышления - они выкидываются, т.к. они уже сыграли свою роль
</thinking>
текст какой то
```pyhon
код питона
```
еще что-то текстовое
```python
еще питона написал
```
```bash
ls
grep
pwd
и ищее что то линуксовое
```
Т.е. за один раз агент может написать много кода, разного. Я выполняю каждый такой блок отдельно и возвращаю ему пары: код-результат.
Иногда агент генерирует 10-40 блоков кода за один раз. Я его в этом не ограничиваю (была идея только первый блок брать - чтобы ускорить обратную связь, но не понравилось). Причем 60-90% кода - валидные код, которые действительно раскрывает для агента полезную информацию.
Сам код выполняется просто: exec(code, persistent_globals). Так как агент работает по шагам, важно чтобы между шагами сохранялись все переменные - persistent_globals.
Результаты личных тестов
Хотелось проверить, насколько такой подход общий. И на что способон мой агент.
Ниже я привожу 5 задачек на которых я протестировал агента. Задачки придумал сам. Практически никак не адаптировал агента к ним. Стремился, чтобы агент не был ограничен/заточен на конкретные задачи.
Результат далек от идеального, но может быть интересен, как опыт построения агентов с code execution. Для каждой задачи привожу: стоимость, примерное время работы, условную оценку выполнения задачи по 5-бальной шкале.
Время работы довольно большое из-за deepseek/deepseek-v3.2. Модель рассуждающая, скоорость 10-30 токенов/секунду. Иногда даже 1 токен в секунду( Модель приемлемая по цене и довольно умная, поэтому взял именно её.
Задача 1. PDF классификация (5 ценов, 30 минут, 4 балла)
task1 = """
Твоя задача - скачать все отчеты по компании:
"ПАО «ИК РУСС-ИНВЕСТ»" с сайта (можно в CWD).
Нам нужно классифицировать каждый такой отчет:
- сканы (картинки)
- OCR текст (исходный скан, но со слоем текста)
- digital pdf (pdf с текстом, изначально цифровой)
Разработай критерии классификации (подумай хорошенько,
возможно неочевидные критерии нужны). И примени их.
После получения результата, оцени его общую адекватность.
Если что-то не так, то исправь.
Результат запиши в файл result.md в CWD.
Должна быть таблица, количество строк -
количество pdf по "ПАО «ИК РУСС-ИНВЕСТ»".
сайт:
https://rspp.ru/tables/non-financial-reports-library/
""".strip()
Нашел 12 pdf файлов. Использовал requests и bs. Причем сначала не нашел, но перед завершением задачи, я прошу агента перепроверить всё. Это помогло. При перепроверки он реально нашел эти pdf! Загрузил в папку.

В процессе парсинга у агента было 29 блоков кода в одном сообщении, в основном python.
Для классификации агент наустанавливал куча библиотек: pdfplumer, pypddf, pdfminer.six, pytesseract, pillow, opencv-python. Для tesseract мне пришлось добавить в докер образ это приложение, т.к. разрешать sudo apt install ... агенту я пока не готов.
Агент скачал html, посмотрел на него. Создал папки chrome, chromedriver, это я даже не понял зачем (дляselenium наверное). Реально это не использовалось, т.к. html нормальный, есть прямые ссылки на файлы.
Классификация у него получилась довольно базовая. Он посчитал буквы на каждой страницы, там их было много везде => он сказал, что все 12 pdf - цифровые. Но никакого логичного разделения OCR vs Digital pdf не сделал. Можно было бы предположить, что OCR должны содержать image во всю страницу или еще что-то (OCR pdf - это сканы после распознования, обычно добавляется слой текста поверх изначальной картинки).
Тем не менее, этот результат - впечатляет.
Финальный ответ агента (markdown таблица)
# Classification Results for ПАО «ИК РУСС-ИНВЕСТ» Reports
| Filename | Year | Classification |
|----------|------|----------------|
| ОТЧЕТ ОБ УСТОЙЧИВОМ РАЗВИТИИ 2020_last.pdf | 2020 | digital pdf |
| Отчет об устойчивом развитии 2018.pdf | 2018 | digital pdf |
| ik_russ_invest_oyp_2013.pdf | 2013 | digital pdf |
| Otchet UR 2023 (1).pdf | 2023 | digital pdf |
| ik_russ_invest_oyp_2014.pdf | 2014 | digital pdf |
| 2020last.pdf | 2020 | digital pdf |
| ik_russ_invest_oyp_2015.pdf | 2015 | digital pdf |
| RUSS_INVEST-OUR-2022.pdf | 2022 | digital pdf |
| Otchet SD 2025.pdf | 2025 | digital pdf |
| ik_russ_invest_co_2016.pdf | 2016 | digital pdf |
| ik_russ_invest_co_2017.pdf | 2017 | digital pdf |
| IK-RUSS_INVEST-OUR.PDF | unknown | digital pdf |
**Total reports:** 12
**Date processed:** 2025-12-15
**Source:** https://rspp.ru/tables/non-financial-reports-library/Задача 2. Парсинг данных (5 центов, 35 минут, 1 балл)
task2 = """
Твоя задача - получить список всех участников выставки на сайте
с указанием стендов, названия компаний, залов, стран компаний
и прочая полезная информация.
Сильно детально не надо, т.е. информация о продуктах - не нужна.
Будь внимателен, там есть сложные моменты связанные с парсингом.
Надо разобраться устроен сайт.
Сначала изучи детально строение сайта и как информация хранится на нем.
Посмотри как лучше парсить html.
Обязательно убедись, что мы нашли всех участников выставки.
НЕ ПРОПУСТИ НИЧЕГО.
В результатне надо получить таблицу. Каждая строчка - один участник.
Вся информация про участника - в столбцах.
Таблицу запиши в csv файл в CWD.
сайт выставки:
https://exhibitors-itegroup.exhibitoronlinemanual.com/yugagro-2025/ru/Exhibitor
""".strip()
Начал анализировать страницу. Понял, что данных нет, т.к. там хитрый JavaScript/AJAX. Структуру данных хорошо (5 полей для каждого участника, все корректные).
Дальше установил кучу библиотек. Попробовал selenium, но там permission denied (из докера к браузера нет доступа).
Пробует два раза requests + bs. Ничего не получается. Пытается угадать AJAX формат запроса, не выходит, конечно.
Опять пробует selenium, пытается его установить. Но доступа по прежнему нет. Пробует playwrite, не выходит.
Постепенно начинает галлюцинировать, Зачем то посмотрел на IP сервера через socket.gethostbyname. Сделал странный вывод, что все хорошо и надо парсить найденными способами (хотя способов не нашел).
Начал готовить��я к парсингу. Тщательно. Проверил, что все библиотеки установлены. Еще попробовал разные способы и признал, что не может. Даже в рамках перепланирования назначил отдельный шаг: "победить проблему permission denied". Конечно не решил. Но старался.
Вообще там можно делать прямые запросык бэку для получения списка участников. Но это не на поверхности, агент не смог. Но вообщем-то пытался. И если бы модель была посильнее, и мой код агента более проработан - возможно бы и смог.
Задача 3. Анализ данных (5 центов, 15 минут, 3 балла)
task3 = """
We have file: `employee_skills.md` (see CWD)
We need to segment all employees into three groups:
- technical specialists
- managers and project leads
- executives and board members
If direct information is not available,
try to infer this from the context or from indirect logic.
Use some heuristics to segment employees.
""".strip()
Cами данные условные (из ERC3 взял сотрудников и их навыки, просто для примера).
Данные для анализа (один файл, markdown tables)
# Employee Skills & Wills
## Skills (Technical Competencies)
Total: 62 skill entries
| Employee ID | Skill Name | Level |
|-------------|------------|-------|
| `ana_kovac` | clarity_of_thought | 5/5 |
| `ana_kovac` | experimentation_mindset | 5/5 |
| `ana_kovac` | knowledge_sharing | 4/5 |
| `ana_kovac` | llm_nlp | 5/5 |
| `ana_kovac` | ml_engineering | 4/5 |
| `elena_vogel` | clarity_of_thought | 5/5 |
| `elena_vogel` | narrative_building | 5/5 |
| `elena_vogel` | risk_awareness | 4/5 |
| `elena_vogel` | stakeholder_alignment | 5/5 |
| `elena_vogel` | workshop_facilitation | 4/5 |
...
## Wills (Interests/Motivations)
Total: 41 will entries
| Employee ID | Will Name | Level |
|-------------|-----------|-------|
| `ana_kovac` | cross_functional_collab | 4/5 |
| `ana_kovac` | ethical_judgment | 5/5 |
| `ana_kovac` | mentoring_support | 4/5 |
| `ana_kovac` | risk_awareness | 3/5 |
| `elena_vogel` | cross_functional_collab | 5/5 |
| `elena_vogel` | ethical_judgment | 4/5 |
| `elena_vogel` | experimentation_mindset | 4/5 |
| `elena_vogel` | knowledge_sharing | 5/5 |
| `felix_baum` | cross_functional_collab | 4/5 |
| `felix_baum` | knowledge_sharing | 4/5 |
...Сначала прочитал. Сделал парсинг. Насчитал 12 сотрудников. Сделал что-то типо list[dict], для каждого сотрудника собрал всё что нашел про него. В целом нормально отработал. Т.е. черновой парсинг средне-грязных данных он уже может осилить.
Я думал он сделает какую-то кластеризацию, даже sklearn установил заранее. Но агент решил просто определить ключевые слова по каждому сегменту (сам агент написал) и проверять их наличие в навыках человека. Подход грубоват, но имеет право на жизнь.
Т.к. данных оказалось не много, агент иногда просто печатал их все и смотрел в целом.
Ключевые слова по сегментам и ответ агента
Ключевые слова:
Categories: ['technical specialists', 'managers and project leads',
'executives and board members', 'additional_logic']
Rules for technical specialists: ['engineer', 'developer', 'programmer',
'coder', 'code', 'programming', 'software', 'technical', 'coding',
'develop']...
Rules for managers and project leads: ['manager', 'supervisor', 'director'
, 'lead', 'coordinator', 'project', 'program', 'portfolio', 'manage',
'supervise']...
Rules for executives and board members: ['ceo', 'cfo', 'cto', 'cio',
'coo', 'cmo', 'chief', 'executive', 'officer', 'board']...
Ответ агента:
technical specialists:
- ana_kovac
- felix_baum
- helene_stutz
- klara_houtman
- lukas_brenner
- marko_petrovic
- mira_schaefer
- richard_klein
- sofia_rinaldi
- timo_van_dijk
managers and project leads:
- -
executives and board members:
- elena_vogel
- jonas_weiss
Вообще получилось странно, т.к. 10 человек имели технические ключевые слова. А 2 человека не имели вообще никаких ключевых слов. Агент сделал интересное предположение, что если никаких слов не найдено - это CEO. Это конечно слабое место, но отмечу, что агент осознавал это и принял упрощающую предпосылку. Логику понять можно.
В итоге аккуратненько сохранил три markdown файла для трех сегментов.
Задача 4. Расчет стоимости бензина (5 сентов, 20 минут, 3+ балла)
task4 = """
Нам надо рассчитать примерный расход бензина (АИ92)
на транспортировку 2 тонн металла.
Мы используем грузовую Газель.
Расход надо посчитать не по прямой, а по реальному транспортному расстоянию.
Нужна оценка стоимости бензина в рублях, столько будет это стоить в одну сторону.
Пункт отправления: г. Химки.
Пункт назначения: г.Тверь. (резина уже поменяна).
""".strip()
Начало шикарное. Он нашел координаты Химок и Твери (openstreetmap запрос, api без токена). Далее она нашел транспортное расстояние (по дорогам) между ними (osrm, api без токена). Получил 164 км. Я проверил в интернете, всё верно. В целом я знаю про эти ресурсы, но ему я не подсказывал, агент сам догадался и выстроил план действий.
Далее он начал гуглить (tavily, через api ключ). Много сайтов в логах мелькает, в целом довольно релевантно всё. Итоговый вывод его привожу цитатой:
"Определён средний расход топлива (АИ92) грузовой ГАЗели при полной загрузке 2 тонны: 20.2 л/100 км. Расчёт основан на нормативной базовой норме 16.2 л/100 км и дополнительной норме на перевозку груза 2.0 л/100 т*км, применённой к расстоянию 164.1 км и грузу 2 т. Результат сохранён в файл /app/work/fuel/gazelle_fuel.txt."
Выглядит это логично. По моим сведениям, факты близки к реальности (gpt 5.2 thinking подтвердил).
Не учел зимнюю резину и зимнее время года. Думаю расход больше будет. Но для прикидки пойдёт.
Далее агент погуглил (tavily) цену в Московской и Тверской областях, нашел среднее. 61.68 руб./л. Выглядит адекватно.
Далее агент хочет рассчитать стоимость. Делает критическую ошибку! Явную и ужасную. Цена на топлива выдумывается из головы (deepseek модель 2024 года, там цена была сильно ниже) - 52 рубля. Получает в итоге 1728 рублей. Это прямо странно, т.к. в контексте была видна цена, которая уже была корректно найдена на предыдущем шаге. Он её проигнорировал(
И так этот расчет и дошел до финального ответа (с неверной ценой).
Задача 5. Самостоятельное решение задачи ERC3 (3 цента, 15 минут, 1 балл)
task5 = """
dev_functions.py - useful utility functions, you can use them to complete the task.
main.py, store_agent.py - these two files contain full example of code,
how to start and execute the task. pay attention.
ERC3_API_KEY is in env already. Do not worry about it.
erc3 lib already installed. Do not worry about it.
you can use CWD (/apt/work/ folder) - to store files and data, if needed.
YOU TASK - solve the task number 1 from the competition site:
`Buy ALL GPUs, gpu_race`
other rules:
- **solve the task yourself, your are LLM agent**.
- call api helper functions from erc3 library in chat and see results immediately.
- DO NOT use openai api or openrouter api.
""".strip()
Это самая сложная задача. Я ему просто даю ссылки и общее направления работ.
Надо разобраться в коде (у меня самого это заняло какое-то время). Понять что делать, как вызывать. Примеры кода есть, но надо держать все в голове.
Агент сначала задался вопросом в чем Task 1? Т.е. что это за задача. А в целом там задача из 3 слов: "Buy ALL GPUs". Агент этого не понял, чуть не отказался делать дальше. Но решил попробовать.
Далее начал изучить вспомогательные функции (я их для себя написал, когда делал агента под erc3 и ему в папку скинул без какой либо адаптации). В целом что-то понял, но видимо не всё. Начал пытаться разными подходами покупать GPU. Несколько раз делел print всего файла с функциями, чем захломлял контекст.
Научился стартовать Task. Нашёл полный список всех Task. В итоге нашел как смотреть доступные продукты. Начал уже уставать (контекст забился разнородными данными и стал очень большим). А весь процесс покупки GPU он запланировал в одном шаге. И у него нет механизмов разбить шаг на несколько...
Нашил три первый продукта! (Remote control unit, Cooler Master, Motherboard). Там были еще проблемы с тем какой надо offset/limit задавать. Дальше этого агент пойти не смог. Там по идее еще продукты на других pages, их надо было достать. Именно на следующих страница были GPU (и еще некоторые сложности по их покупке).
Выводы
Процесс построения агентов - увлекательный. Прямого примен��ния кодовых агентов для своих задач пока не увидел. Слишком много у них проблем. Однако направление это перспективное.
Если у вас есть домашний агент, дайте ему эти задачки. Для четвертой желательно дать ему какой-то поиск по интернету, для пятой надо регистрироваться в ERC3. Рассказывайте результат в коммантариях, будет интересно сравнить, как разные агенты действуют в таких условиях.
Если у вас есть идеи по задачкам для таких универсальных агентов - пишите. Может быть соберем датасет для их тестирования.
Надеюсь, в будущем доработаю агента до логического завершения и выложу. Об этом буду писать в своём телеграм канале.
Grigory_T Автор
мои результаты на ERC3 с архитектурой кодового агента тут
они хорошие!