5. Инструменты — основы
🔵 Общая механика всех инструментов: поля YAML, шаблоны MiniJinja, визуальные блоки, встроенные движки. Сводную таблицу всех движков см. в «Справочник инструментов».
5.1 Общие поля
Каждый инструмент-YAML разделяет общие верхнеуровневые поля:
| Поле | Описание |
|---|---|
kind |
дискриминатор движка (обязательно) |
name |
имя инструмента, которое вызывает LLM (по умолчанию — имя файла) |
description |
текст, показываемый LLM для function-calling |
parameters |
JSON Schema аргументов инструмента |
ui |
рендер в виджете: icon, call_template, result_template, failure_template, плюс result_blocks / chart / table |
visual |
UI-only payload (упорядоченный список блоков) поверх сырого extracted — показывается пользователю, никогда не попадает в контекст LLM |
warnings |
декларативные правила предупреждений, всплывающие в трейсах |
ui
ui:
icon: 🚗
call_template: "Ищу {{ input.query }}..." # до выполнения
result_template: "{{ extracted.total }} найдено" # после успеха
failure_template: "⚠️ {{ error }}" # после ошибки
Шаблоны — MiniJinja. call_template
видит input; result_template видит extracted. При неудаче
(success: false) result_template пропускается, а failure_template (если
задан) рендерится с error (сообщение), status (HTTP-статус, если есть),
extracted (распарсенное тело ошибки, если JSON), content (сырьё) и
success: false. Без failure_template показывается сырой текст ошибки.
Визуальные блоки (графики и таблицы)
Инструмент может вернуть визуальный слой — упорядоченный список типизированных
блоков (text, chart, table, file). Блоки рендерятся в веб-виджете
(Chart.js + таблицы + ссылка на скачивание файла), Android (Vico + Compose) и
Telegram (PNG + таблица + документ).
Два слоя: данные для LLM и презентация для UI
Результат инструмента служит двум потребителям, и их нельзя смешивать:
| Слой | Кому | Что несёт |
|---|---|---|
content (строка) |
LLM | компактная сводка результата |
visual (опционально) |
UI | полные данные / готовые блоки, минуя LLM |
result_blocks |
клиенту | упорядоченные блоки, отправляемые по проводу |
content по-прежнему уходит в контекст модели; visual — только в UI и
никогда в LLM. Клиент вычисляет result_blocks либо из visual, либо из
content + ui-шаблонов.
Способы задать блоки
-
ui.result_blocks/ui.chart/ui.table— декларативные шаблоны поверхextracted:ui: result_blocks: - type: text markdown: "Найдено **{{ extracted.count }}**" - type: table columns: [{ key: model, title: "Модель" }] rows: "{{ extracted.items | tojson }}"ui.chart:иui.table:— сокращения для одного блока;result_template:— одинtext-блок. -
visual— верхнеуровневое поле, рендерится поверх сырогоextracted(неcontent), уходит напрямую в UI, аcontentостаётся компактной сводкой:output: count: "{{ extracted.items | length }}" # компактная сводка → LLM visual: - type: table rows: "{{ extracted.items | tojson }}" # полные данные → только UI -
Специализированные движки —
chart_tool/table_tool/visualize_toolсами заполняютcontent(сводка) иvisual(полный блок). Скриптовые инструменты задаютvisualключом вrun(args)(см. 07-scripts). -
Fenced-блоки в ответе модели —
```chart {…}и```tableв markdown-ответе парсятся клиентом.
Формат блоков
Блок chart несёт spec:
{
"type": "bar", // bar | line | area | pie | scatter
"title": "Цены",
"labels": ["Q1", "Q2", "Q3", "Q4"],
"series": [ { "name": "Цена", "values": [10, 20, 15, 30] } ],
"options": { "stacked": false }
}
Блок table несёт columns + rows (массив объектов), опционально title,
page_info и options (sortable/searchable/paged):
{
"type": "table",
"columns": [
{ "key": "model", "title": "Модель", "align": "left" },
{ "key": "price", "title": "Цена", "align": "right" }
],
"rows": [ { "model": "A", "price": 100 } ],
"page_info": { "returned": 50, "total": 500, "has_more": true },
"options": { "sortable": true, "searchable": true }
}
Блок file несёт файл для скачивания — name (имя файла), mime и data
(base64-содержимое). Создаётся движком file_tool:
{
"type": "file",
"name": "report.html",
"mime": "text/html",
"data": "PGgxPkhpPC9oMT4="
}
Ленивая пагинация (continuation)
Блок table может нести page_info и continuation — клиент запрашивает
следующую страницу через POST /v1/continuations с id, сервер повторно вызывает
инструмент с сохранёнными аргументами (без LLM-раунда). Web — infinite scroll,
Telegram — кнопка «Load more». Первая страница рендерится всегда; мёртвый id
просто отключает подгрузку.
warnings
warnings:
- contains: '"total_server": 0' # подстрока в сериализованном выводе
message: "Нет результатов"
- failed: true # срабатывает при success=false
message: "Инструмент упал"
Сработавшие предупреждения видны в трейсах (trace_sessions, trace_search).
5.2 Шаблоны и переменные
Инструменты используют MiniJinja (подмножество Jinja2) в полях-шаблонах:
url, заголовки, тело запроса, call_template / result_template /
failure_template, output, указатели в extract, summary, computed.
Контекстные переменные
| Переменная | Где доступна | Значение |
|---|---|---|
input |
fetch (url/headers/body), extract (указатели), call_template, output |
аргументы вызова инструмента |
extracted |
result_template, output, visual |
извлечённые поля |
item |
json_tool.computed |
текущий элемент результата |
count |
summary (chart/table/visualize) |
число элементов |
error / status / content / extracted |
failure_template |
детали ошибки (сообщение, HTTP-статус, сырое тело, распарсенное тело) |
env_var('NAME') |
везде (функция) | значение переменной окружения процесса |
Встроенные фильтры MiniJinja
| Фильтр | Описание |
|---|---|
slugify |
в нижний регистр, неалфавитно-цифровые → _ |
transliterate |
кириллица → латиница (для slug) |
urlencode |
percent-encoding для URL |
tojson |
сериализация значения в корректный JSON (true/false/null, кавычки) |
strip_html |
убрать HTML/XML-теги |
fromunixtime |
unix-время → строка даты |
кастомные из filters: |
таблица ключ→значение (lookup) с case_insensitive и default |
Пост-рендер: MiniJinja выводит null/булевы как None/True/False — движок
преобразует их обратно в корректный JSON null/true/false.
Переменные в инструкциях агента
В instructions: агента доступны подстановки, заполняемые ядром при создании
сессии (пишутся заглавными в двойных подчёркиваниях):
| Плейсхолдер | Значение |
|---|---|
__DATE__ / __WEEKDAY__ / __TIME__ |
текущая дата / день недели / время (локальное сервера) |
__GEOIP__ |
город пользователя (резолв по IP; unknown, если не определён) |
__COUNTRY__ / __COUNTRY_CODE__ |
страна / код страны |
__USER_ID__ |
id пользователя |
__ADMIN_TEMPLATES__ |
скоуп видимости админа (* или список шаблонов) |
Пример из drom-agent: User's city: __GEOIP__. If user doesn't specify region, use this city.
5.3 Встроенные инструменты
Реализация уже в ядре, YAML не нужен — перечисли имя в tools: в agent.yaml.
| Имя | Назначение | Ключевые параметры |
|---|---|---|
http_fetch |
скачать URL | url, max_chars (по умолчанию 8000, 0=всё), start_char |
fs_read |
прочитать файл | path, max_chars, start_char |
job_done |
сигнал завершения | reason (или схема output_schema) |