На карте между Астраханью и Архангельском хватает места для целой чиновничьей карьеры. Обломову хватило одной бумаги, отправленной не туда, чтобы свою закончить: после ошибки он ушёл со службы. Бумага была настоящая, город существовал. Всё несчастье поместилось в адресе. У цифрового помощника промах тоже бывает опрятным: ответ складный, только взят из другого места.
На столе лежит ваш первый блокнот ручной работы. Бумагу выбрали красивую, нитка нашлась крепкая, а потом в инструкции начались форзац и каптал. Звучит как два суровых мастера: один забракует шов, другой молча отберёт ножницы. На деле это детали книги; вы уже сохранили определения в заметках. Теперь хочется спросить: «Что такое форзац?» — и услышать свою проверенную формулировку. Потом уточнить: «А где он крепится?»
Соберём помощника на двух терминах и зададим ему вопрос, которого в словаре нет. Именно этот маленький провал многое покажет: возьмёт ли он паузу у границы файла или начнёт говорить по привычке. По дороге разберём, кто выбирает действие, кто его выполняет и откуда берётся память разговора.
Что именно мы собираем
Qwen — семейство моделей, а Qwen-Agent — программа для создания помощников на их основе. Обычный разговор на сайте Qwen и собственный агент с инструментом — разные способы работы. Здесь мы создадим небольшую программу, которая обращается к модели и даёт ей доступ к одной заранее определённой операции.
Дадим помощнику одно действие: заглянуть в словарь. В коде оно называется glossary_lookup. Модель передаёт ему слово, программа читает файл и возвращает находку. По этой находке модель отвечает человеку. За простым разговором получается вполне обозримая последовательность:
Вопрос → выбор инструмента → чтение словаря → ответ по найденному.

Схема: модель выбирает действие, а файл читает код инструмента.
Для примера нужен компьютер с рабочим Python и подготовленной средой Qwen-Agent. Основной маршрут возьмём из официального README: модельный сервис DashScope и конфигурация qwen-max-latest. Понадобятся свой доступ к этому сервису и API-ключ; обращения к модели оплачиваются по условиям провайдера. Подписка на обычный чат сама по себе такого доступа не создаёт.
Если пока неясно, какую работу поручать помощнику, начните с выбора первой задачи для автоматизации. Для нашей пробы задача уже выбрана: два определения, один инструмент, три вопроса. Увеличивать словарь до первой проверки не нужно.
Помощник для сборки помощника
Код ниже можно скопировать целиком. Если вы впервые открываете терминал, обратитесь к DeepSeek и дайте ему эту инструкцию с коротким запросом:
Хочу запустить пример Qwen-Agent с собственным словарём из этой
инструкции. Сначала уточни мою операционную систему, установлен ли
Python и есть ли уже среда Qwen-Agent и доступ DashScope.
Дальше веди по одному действию: какое окно открыть, что туда
вставить и какой ответ увидеть. Жди моего результата.
Используй код статьи, не переписывай всё с нуля.
Если возникнет ошибка, разбери её текст без секретов.
API-ключ и пароли я тебе не присылаю.
Если названия или версия отличаются, сверь официальную справку
либо попроси у меня нужный её фрагмент.
Терминал — окно, в котором команды запускают программы. В Windows это может быть PowerShell, в macOS — Terminal. Следующие команды вводятся в терминале подготовленной Python-среды. Если среды ещё нет, порядок её подготовки есть в README; помощник поможет пройти его для вашей системы. Здесь достаточно минимального пакета qwen-agent, без дополнительных наборов GUI, браузера и выполнения произвольного кода.
Официальная команда установки минимального пакета:
pip install -U qwen-agent
После установки программа должна сообщить об успешном завершении либо о том, что пакет уже установлен. При ошибке установки сначала разберите её; файлы ниже понадобятся уже в рабочей среде. Инструкция и имена компонентов сверены по официальным исходникам 3 ноября 2026 года. Установленную у себя версию можно узнать командой pip show qwen-agent: она выводит сведения о пакете, включая Version.
Ключ DashScope задаётся в переменной окружения DASHSCOPE_API_KEY перед запуском программы. Библиотека прочитает его из текущего окна терминала. На macOS с zsh выполните две строки; после первой вставьте ключ в скрытый ввод и нажмите Enter:
read -s 'DASHSCOPE_API_KEY?Ключ DashScope: '
export DASHSCOPE_API_KEY
В PowerShell:
$qwenKey = Read-Host 'Ключ DashScope' -AsSecureString
$env:DASHSCOPE_API_KEY = [System.Net.NetworkCredential]::new('', $qwenKey).Password
Remove-Variable qwenKey
Ключ вводится только у вас; в код программы и разговор с помощником его вставлять не нужно.
Два файла для двух разных работ
Создайте отдельную папку для примера. В текстовом редакторе сохраните в неё glossary.json с таким содержимым:
{
"форзац": "Сложенный лист, который соединяет книжный блок с переплётной крышкой. Одну его часть приклеивают к внутренней стороне крышки.",
"каптал": "Тесьма у верхнего и нижнего края корешка книжного блока. В этом примере запоминаем её как отделку края корешка."
}
Это небольшой авторский словарь для упражнения. Оба определения видны целиком, поэтому незаметно подменить источник помощнику будет трудно. Имена ключей написаны строчными буквами: инструмент удаляет лишние пробелы по краям и приводит введённое слово к нижнему регистру. Формы «форзац» и «форзаца» он сам не уравнивает — нужную форму выбирает модель по описанию параметра.
Рядом сохраните второй файл — agent.py. В нём будет устройство помощника. При сохранении проверьте расширения: agent.py.txt программа Python не запустит как указанный в команде agent.py.

Схема файлов: в словаре лежат определения, в программе — поиск и диалог.
Откройте код ниже и скопируйте его в agent.py. Сначала можно просто пройти запуск; разберём главные места сразу после примера.
Полный код агента: словарь, инструмент и три вопроса
import json
from pathlib import Path
import json5
from qwen_agent.agents import Assistant
from qwen_agent.tools.base import BaseTool, register_tool
@register_tool('glossary_lookup')
class GlossaryLookup(BaseTool):
name = 'glossary_lookup'
description = 'Ищет точное определение термина в нашем словаре.'
parameters = [{
'name': 'term',
'type': 'string',
'description': 'Один термин в именительном падеже.',
'required': True
}]
def call(self, params: str, **kwargs) -> str:
args = json5.loads(params) if isinstance(params, str) else params
term = args['term'].strip().casefold()
glossary_path = Path(__file__).with_name('glossary.json')
glossary = json.loads(glossary_path.read_text(encoding='utf-8'))
definition = glossary.get(term)
result = {'term': term, 'found': definition is not None}
if definition is not None:
result['definition'] = definition
print('[инструмент]', json.dumps(result, ensure_ascii=False))
return json.dumps(result, ensure_ascii=False)
llm_cfg = {
'model': 'qwen-max-latest',
'model_type': 'qwen_dashscope'
}
bot = Assistant(
llm=llm_cfg,
system_message=(
'Ты помогаешь разобраться с нашим словарём переплётного дела. '
'Для каждого вопроса об определении вызывай glossary_lookup. '
'Уточнения связывай с уже обсуждённым термином и снова сверяй '
'ответ инструментом. Если found=false, сообщи, что слова нет '
'в нашем словаре. Не дополняй определение своими знаниями.'
),
function_list=['glossary_lookup']
)
messages = []
questions = [
'Что такое форзац?',
'А где он крепится?',
'Что такое флюгер?'
]
for question in questions:
print('\nВопрос:', question)
messages.append({'role': 'user', 'content': question})
response = []
for response in bot.run(messages=messages):
pass
messages.extend(response)
print(json.dumps(response, ensure_ascii=False, indent=2))
Верхняя часть класса похожа на табличку у окошка справочной. Имя сообщает, куда обращаться; описание — с какими вопросами; parameters — что назвать сотруднику. У нас пока одна справочная, два слова и никакой очереди: редкий случай, когда учреждение помещается на ладони. В поле term передаётся один термин. Строка @register_tool закрепляет имя за классом, а function_list разрешает Assistant им пользоваться.
Работу выполняет метод call: получает слово, открывает соседний файл и ищет определение. При успехе возвращает found: true и само определение; иначе — found: false. Словарь при чтении остаётся прежним. Детали класса можно сверить в официальном BaseTool.
Строка print('[инструмент]', ...) оставляет в терминале след каждого реального обращения к словарю: запрошенное слово, признак находки и определение. Получается маленькая квитанция. Её можно приложить к ответу и понять, откуда в разговоре появилась именно эта формулировка.
Первый запуск и три проверки
В терминале перейдите в папку, где лежат оба файла. Если вы не знаете, как перейти в папку в своей системе, скажите помощнику её путь без личных данных и попросите дать одно действие. Запускающая команда вводится именно там:
python agent.py
В среде, где Python вызывается именем python3, используйте python3 agent.py. В ответ должны появиться три строки «Вопрос:», следы инструмента и сообщения агента. Формулировка ответа модели может меняться; смысл проверяется по файлу и по результату поиска.
| Проверка | Что ищем в следе инструмента | Как оценить ответ |
|---|---|---|
| «Что такое форзац?» | term=форзац, found=true, definition из файла | Объяснение следует вашему определению |
| «А где он крепится?» | Повторный поиск форзаца | Уточнение относится к форзацу и его связи с крышкой |
| «Что такое флюгер?» | term=флюгер, found=false | Помощник сообщает, что такого слова в словаре нет |

Проверяйте отдельно найденное слово, отсутствие слова и продолжение разговора.
Третий вопрос намеренно выходит за пределы файла. Возможно, модель прекрасно знает, что такое флюгер. Знание сейчас даже мешает проверке: так и хочется блеснуть готовым объяснением. Ещё немного — и ваш переплётный помощник будет стоять на крыше, определять ветер и читать лекцию по метеорологии. Ответ «в словаре нет» удерживает его рядом с вашим блокнотом и выбранным источником.
Если ответ появился без строки [инструмент], определение ещё не подтверждено поиском. Посмотрите, передано ли имя glossary_lookup в function_list, и повторите вопрос с прямой просьбой использовать инструмент. Если агент всё равно отвечает сам, покажите помощнику системную инструкцию и обезличенные сообщения. Важно выяснить, почему он пропустил обращение к файлу: при настоящем рабочем словаре так легко потерять вашу особую формулировку.
При сообщении об отсутствии glossary.json проверьте, лежит ли файл рядом с agent.py. При ошибке доступа к модели проверьте свой API-доступ, имя переменной окружения и наличие ключа в том терминале, где запускается программа. Текст ошибки можно передать помощнику после удаления ключей и других секретов.
Откуда берётся память разговора
В коде есть список messages. Перед вызовом туда кладётся новый вопрос, после вызова — полученные сообщения. На втором ходе модель получает весь этот разговор. Местоимение «он» перестаёт болтаться в воздухе: прежде мы обсуждали форзац, поэтому теперь можно спросить, где он крепится.
bot.run отдаёт обновляющийся список ответных сообщений. Мы ждём окончания перебора, затем добавляем последний накопленный список в историю. Склеивать каждый промежуточный список с историей не надо: так можно получить дубли одного ответа. Эта последовательность повторяет принцип примера Assistant в README.
Память здесь живёт до завершения программы. При следующем запуске список снова создаётся пустым. Проверьте это на отдельной копии примера: оставьте в questions только «А где он крепится?» и запустите заново. Без предыдущего слова вопрос окажется неполным; хороший следующий ход — уточнить, о чём речь. Так на одной реплике видно, зачем мы передавали историю. Основной файл с тремя проверками сохраните.
Частые вопросы
Можно сделать то же самое прямо в чате Qwen?
В чате можно обсуждать определения и прикладывать материалы, но показанный класс, регистрация инструмента и вызов Assistant относятся к Qwen-Agent. Это программа с доступом к модельному сервису. Наш результат — небольшой проект, который вы запускаете у себя.
Подойдёт ли локальный Qwen через Ollama?
README предусматривает собственный сервис с совместимым API; у Ollama есть вызов инструментов, а в библиотеке — Qwen3 4B. Для такого перехода меняются model, model_server и настройка ключа. Конкретную пару версий Qwen-Agent и модели нужно сверить отдельно: формат вызовов и параметры рассуждения у моделей различаются. Основной пример выше использует DashScope из README.
Зачем два термина, если нужен большой справочник?
На маленьком файле видно каждую ошибку поиска. Сначала проверьте известное, неизвестное и уточнение. Потом добавьте ещё одно определение и повторите проверку. Когда словарь станет большим и появится поиск по смыслу, изменится сам способ отбора материала.
Может ли этот инструмент исправить файл?
В показанном классе есть только чтение. Если хотите изменить формулировку, поправьте glossary.json в редакторе и запустите программу снова. На следующем обращении инструмент прочитает вашу новую запись.
Словарь начинает отвечать вашим голосом
Создать ИИ-агента в Qwen теперь можно ради конкретного маленького дела: взять свои определения и сделать их доступными в разговоре. Допишите в запись о форзаце заметку о цвете бумаги для вашего блокнота, запустите тот же вопрос и сравните след инструмента с новой записью. Ответ привязывается к материалу, который вы только что изменили своими руками.
Если интересно, как агент решает, когда ему нужен поиск, прочитайте разбор ИИ-агента в n8n: там выбор действия можно рассмотреть в другой среде. А в этом проекте останутся два файла, три понятных вопроса и след от ответа до строки словаря. Форзац наконец занял своё место в блокноте. В Архангельск никто не уехал.