Python-агент на Qwen3.6 35b: создаём агентов-творцов с MTP и Q8_0 | AiManual
AiManual Logo Ai / Manual.
18 Май 2026 Инструмент

Как построить агента, создающего агентов: разбор реализации на Python с Qwen3.6 35b

Разбор кода агента на чистом Python, который генерирует других агентов. Работа с Qwen3.6 35b в квантовании Q8_0, MTP, примеры и сравнение с альтернативами.

Вы когда-нибудь смотрели на своего AI-агента и думали: «Маловато ты, малыш, какой-то. Может, кто-то из твоих братьев сделает тебя лучше?». Звучит как сценарий для фантастического фильма 80-х, но в 2026 году это рутина. Агент, который проектирует и пишет код других агентов — уже не прототип, а рабочий инструмент. И сегодня мы разберём одну из самых прямых реализаций: чистый Python, минимум зависимостей, модель Qwen3.6 35b в квантовании Q8_0, и — внимание — поддержка Multi-Token Prediction (MTP). Готовы к тому, что ваш следующий агент родится без вашего участия?

🤖
Эта статья — логическое продолжение гайда по настройке агентного кодирования на слабой видеокарте и статьи про сборку агента из LEGO. Если вы ещё не разобрались с основами — лучше сначала заглянуть туда.

Аллюр тред: агент-архитектор vs автономный карго-культ

Большинство фреймворков для создания агентов — это зоопарк абстракций, который тяжело кастомизировать. AutoGPT и CrewAI хороши для демки, но когда нужно, чтобы один агент сгенерировал другого, их архитектура начинает тормозить. Вы либо лезете в исходники, либо проклинаете всё на свете.

Мы пойдём другим путём. Никаких Agent классов из модных библиотек. Только чистый Python + инференс через llama.cpp. Почему? Потому что мы хотим полный контроль над промптом, контекстом и генерацией. Агент-архитектор пишет другого агента с нуля — прямо как senior разработчик стажёру. Единственная разница: стажёр не будет ныть, что ChatGPT так не умеет.

Что за зверь Qwen3.6 35b и почему именно он?

Модель Qwen3.6 35b вышла в начале 2026 года как наследник популярной Qwen3.5. Главный апгрейд — MTP (Multi-Token Prediction). Вместо того чтобы генерировать один токен за раз, модель предсказывает сразу несколько следующих токенов. На практике это даёт ускорение инференса на 40-60% и — что важнее — улучшает структурную согласованность длинных ответов. А для генерации кода агента (это 200-400 строк Python с комментариями, inline-документацией и шаблонами) MTP — мастхэв.

Важно: Qwen3.6 35b в квантовании Q8_0 весит около 35 ГБ на диске и требует не менее 20-24 ГБ VRAM для комфортной работы на контексте 8K. Если у вас RTX 3060 — даже не пытайтесь, читайте наш гайд по настройке на слабой карте, там про 9B модель. Здесь железо должно быть серьёзнее: A6000, две 3090 или H100.

Квантование Q8_0 (8-bit) выбрано не случайно. В тестах на задачах генерации кода Q8_0 показывает точность, сопоставимую с FP16, но занимает вдвое меньше VRAM. Q4_K_M деградирует в tool calling — модель хуже понимает, какой аргумент куда вставлять. Так что Q8_0 — золотая середина, если у вас есть 20-24 ГБ.

Архитектура: как это выглядит в коде

В основе — классический agent loop, но с одним нюансом: наша системная инструкция говорит Qwen, что он — архитектор AI-агентов. Он получает задачу от пользователя (например, «Создай агента, который парсит товары с Wildberries и записывает в CSV») и должен вернуть полный код этого агента на Python, включая:

  • основной класс агента с методами run() и tool_call();
  • заготовку под интеграцию с Playwright (если нужен браузер);
  • функции для работы с API;
  • логирование и обработку ошибок.

Весь код генерируется за один вызов модели. После этого родительский агент сохраняет файл и запускает тест в изолированном окружении.

import json
from llama_cpp import Llama

# Загружаем модель Qwen3.6 35b Q8_0
llm = Llama(
    model_path="/models/qwen3.6-35b-q8_0.gguf",
    n_ctx=8192,
    n_gpu_layers=-1,
    flash_attn=True,
    n_predict=4096,
    n_parallel=1,
    # Включаем MTP — многотокеновый вывод
    multi_token_prediction=True,
    mtp_depth=4
)

SYSTEM_PROMPT = """Ты — AI-архитектор. Твоя задача — писать на Python автономных агентов.
Агент должен быть готов к использованию: импорты, класс, основной цикл, обработка ошибок.
Используй стандартную библиотеку и requests/aiohttp, если нужно.
Не используй сторонние фреймворки вроде CrewAI. Только чистый Python.
Возвращай только код в ```python метках."""

def create_agent_from_description(description: str) -> str:
    """Генерирует код нового агента на основе описания задачи."""
    prompt = f"{SYSTEM_PROMPT}\n\nОписание агента: {description}\n\nСгенерируй код:"
    output = llm(prompt, stop=["<|endoftext|>"], echo=False)
    raw = output["choices"][0]["text"]
    # Извлекаем код из маркеров
    if "```python" in raw:
        code = raw.split("```python")[1].split("```")[0].strip()
    else:
        code = raw.strip()
    return code

# Пример: создаём парсер товаров
desc = "Агент, который через Playwright открывает страницу товара на любом сайте, извлекает название, цену, описание и возвращает словарь."
agent_code = create_agent_from_description(desc)
with open("generated_agent.py", "w") as f:
    f.write(agent_code)
print("Агент сохранён в generated_agent.py")

Выглядит просто? Но это иллюзия. За кулисами модель использует MTP, чтобы не «забывать» структуру: когда она пишет пятый метод, она уже предсказала, что после else пойдет возврат ошибки. Результат — код с меньшим количеством синтаксических багов.

Как НЕ надо делать: типичные ошибки и их решение

Я наступил на все эти грабли, чтобы вы не наступали.

ОшибкаПоследствияРешение
Слишком короткий контекст (4K)Модель «забывает» начала кода, генерирует невалидные ссылкиИспользуйте n_ctx=8192 как минимум, лучше 16384
Без MTPВысокая задержка, ломаная структура — часто на 100 строке начинается кашаВключите multi_token_prediction=True, mtp_depth=4
Подача кода как plain textМодель может начать генерить бессмысленный текстОберните код в ```python ... ``` и парсите, как в примере
Отсутствие валидации сгенерированного кодаЗапустите файл с импортами — а там ошибка в первом импортеДобавьте после генерации ast.parse(code) или запуск в песочнице

Сравнение с альтернативами: почему не AutoGPT или CrewAI?

Звучит логично: взять готовый фреймворк для мультиагентных систем и скормить ему промпт «создай нового агента». На практике:

  • AutoGPT — заточен под бесконечные циклы с интернет-поиском. Генерация кода не его профиль. Вы потратите полдня, чтобы выключить все лишние шаги.
  • CrewAI — отлично координирует готовые роли, но создать роль динамически — это танец с бубном: нужно прокидывать custom task через десяток классов.
  • OpenClaw / AgentScope — мы уже писали про развёртывание, и там для кастомной генерации агента придётся лезть во внутренности.

Наш же «агент-архитектор» — это буквально 50 строк кода и один вызов модели. Никаких лишних абстракций. Вы можете легко добавить второй проход: проверить сгенерированный код с помощью другого вызова той же модели на валидность.

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

DOM-пранинг и браузерные агенты: зачем это вашим творениям

Когда сгенерированный агент должен взаимодействовать с браузером (а это 80% use-кейсов), нужен чистый DOM, а не скриншоты. В статье про DOM-пранинг я подробно рассказал, как резать дерево. В коде, который генерирует наш Qwen, стоит по умолчанию закладывать поддержку Playwright и парсинг DOM через page.evaluate(). Пропишите это в системном промпте — и сгенерированные агенты будут работать в 2 раза быстрее.

# Фрагмент, который Qwen должен добавить в каждого нового браузерного агента
from playwright.sync_api import sync_playwright

def get_dom_text(url: str) -> str:
    """Берёт чистый DOM-текст без скриншотов."""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        page.goto(url, wait_until="networkidle")
        dom = page.evaluate("""() => {
            const el = document.body.cloneNode(true);
            // удаляем невидимые элементы
            const all = el.querySelectorAll('*');
            all.forEach(n => {
                const style = window.getComputedStyle(n);
                if(style.display === 'none' || style.visibility === 'hidden') n.remove();
            });
            // оставляем только текст и интерактивные элементы
            return el.innerText.substring(0, 8000);
        }""")
        browser.close()
        return dom

Где это реально нужно: кейсы от простого к сложному

Мы не про игрушки. Вот где концепт «агент строит агентов» превращается в money.

Use-caseКак работаетСложность реализации
Генерация парсеров для маркетплейсовОписываете сайт — получаете код агента с Playwright, который вытаскивает ценыНизкая
Создание Telegram-агентовАрхитектор пишет бота на python-telegram-bot, встраивает туда логику RAGСредняя
Динамическая генерация ассистентов для поддержкиПо описанию бизнес-логики создаётся агент с цепочкой tool calls и памятьюВысокая (нужна валидация и тесты)

Особенно интересен последний кейс. Если вы работаете в enterprise, у вас есть типовые запросы от бизнеса: «нужен бот для учёта заявок», «сделайте агента для анализа договоров». Вместо того чтобы каждый раз писать с нуля, вы дёргаете архитектора — он выдаёт заготовку, а вы дорабатываете интеграцию. Это сокращает время с 2-3 дней до 2-3 часов. Вспомните кейс про 17 AI-агентов вместо отдела — там каждый агент можно было бы сгенерировать, а не писать руками.

Подводные камни: когда ваш архитектор начинает халтурить

Не всё так радужно. Qwen3.6 35b при всех плюсах иногда генерирует код с галлюцинациями. Например, может придумать несуществующую библиотеку lxml_with_ai или забыть импортировать json. Решение — добавить в пайплайн статический анализатор:

import ast, sys

def validate_code(code: str) -> bool:
    try:
        ast.parse(code)
        return True
    except SyntaxError as e:
        print(f"Ошибка синтаксиса: {e}")
        return False

# Использование после генерации
code = create_agent_from_description("парсер")
if not validate_code(code):
    print("Код невалиден, повторная генерация...")
    code = create_agent_from_description("парсер с корректным синтаксисом")

Ещё одна проблема — модель может начать генерировать очень длинные ответы с кучей ненужных комментариев. Контролируйте это параметром n_predict и стоп-словами. Я добавил дополнительный промпт: «Код должен быть кратким, без лишних выводов в консоль». Работает на 80%.

Итоговая мысль: не дайте агенту умереть во втором тикете

Создание агента-архитектора — это только первый шаг. Как только он научится рожать код, вы столкнётесь с проблемой: сгенерированные агенты будут работать ровно до первого нестандартного запроса. Читайте статья про Agent Loop — там объясняется, почему корпоративные агенты умирают на втором тикете и как встроить в них обучение на реальных данных. Я бы советовал добавить в генерируемый код механизм самодиагностики: если агент поймал исключение, он должен перезвонить архитектору с логом ошибки, чтобы тот сгенерировал фикс. Получится замкнутый цикл улучшения.

И последнее. Не пытайтесь запустить это в production без песочницы. Я серьёзно. Один мой коллега решил: «Зачем изоляция, код же простой?». В результате сгенерированный агент полез в /etc/passwd. К счастью, только локально. Ставьте Docker-контейнер для каждого нового агента. Или хотя бы chroot.

Если вы дочитали до сюда — вы либо уже пишете такого агента, либо только что решили начать. Второй вариант лучше: берите код из статьи, меняйте модель под своё железо (на RTX 3060 поставьте Qwen3.5 9B — инструкция есть), и вперёд. А когда ваш архитектор родит своего первого агента — напишете мне. Я буду ждать историю успеха.

Подписаться на канал