5. Инструменты — вычисления и действия
🔵 Движки, которые что-то исполняют: скрипты, shell-команды, субагенты, воркфлоу, а также доставка результата (email, файлы). Сводную таблицу всех движков см. в «Справочник инструментов».
5.10 script_tool
Скрипт Rhai или JavaScript.
kind: script_tool
name: currency
description: Конвертация валют.
script: currency.rhai # .rhai → Rhai, .js → JavaScript (QuickJS)
parameters: { ... }
max_operations: 10000000
Скрипт определяет fn run(args) (Rhai) или function run(args) (JS). Полный
справочник — 07-scripts.
5.14 subagent_tool
Делегировать задачу субагенту. Спавнит дочерний агент-процесс, отдаёт задачу, ждёт завершения и возвращает его итоговый ответ. Траты дочернего списываются на сессию родителя (наследует группу бюджета), после — очистка.
kind: subagent_tool
name: delegate_research
description: Делегировать исследование субагенту.
template: trace-agent # или inline instructions + tools:
# instructions: "You are a research assistant."
# tools: [http_fetch, fs_read]
# budget: { max_per_turn: 2000, max_per_minute: 20000, max_total: 20000 }
| Поле | Описание |
|---|---|
template |
шаблон для делегирования (приоритетнее instructions) |
instructions |
inline-инструкции без шаблона |
tools |
имена инструментов субагента (перекрывает шаблон) |
budget |
лимит токенов { max_per_turn, max_per_minute, max_total } |
output_schema |
JSON Schema структурированного результата (субагент завершается job_done; проверенный payload — в data) |
Рантайм-аргументы: task (обязателен), опциональные template/instructions.
5.16 email_tool
Отправить письмо (SMTP).
kind: email_tool
name: send_report
description: Отправить отчёт оператору.
smtp:
host: smtp.example.com
username: agent@example.com
password_env: SMTP_PASSWORD # или password: "..."
from: agent@example.com
tls: starttls # starttls (по умолч., 587) | ssl (465) | none (25)
port: 587
to: ops@example.com
subject: "Agent report"
| Поле | Описание |
|---|---|
smtp.host / username / from |
сервер, логин, From (обязательны) |
smtp.password / password_env |
пароль inline или имя env |
smtp.tls |
starttls (по умолч.) | ssl | none |
to / subject |
дефолты, перекрываемые аргументами |
Аргументы: body (обязателен), опциональные to / subject.
5.17 vk_tool
Вызов VK API от имени сообщества (group access token) — универсальный шлюз плюс удобные действия для типовых бизнес-задач.
kind: vk_tool
name: vk_api
description: Вызвать VK API от имени сообщества.
token_env: VK_GROUP_TOKEN # env с group access token (по умолч. VK_GROUP_TOKEN)
service_token_env: VK_SERVICE_TOKEN # env с сервисным ключом (по умолч. VK_SERVICE_TOKEN)
api_version: "5.199" # версия API (по умолч. "5.199")
owner_id: -123456789 # дефолтный владелец (для wall_post)
| Поле | Описание |
|---|---|
token_env |
имя env с токеном сообщества (групповые действия: send_message, wall_post, generic-шлюз) |
service_token_env |
имя env с сервисным ключом — для поисковых/читающих методов (search), недоступных групповым токенам |
api_version |
версия VK API (по умолч. 5.199) |
owner_id |
дефолтный владелец для wall_post (отрицательный = группа) |
Два режима вызова. Generic-шлюз — любой метод VK API:
{ "method": "wall.get", "params": { "owner_id": -123456789, "count": 5 } }
Удобные действия (внутри движок сам подставляет обязательный random_id
и параметры по умолчанию):
{ "action": "wall_post", "message": "Новый пост от агента" }
{ "action": "send_message", "peer_id": 123, "message": "Привет" }
{ "action": "search", "q": "бренд", "count": 10 }
| Действие | VK-метод | Токен | Что делает |
|---|---|---|---|
send_message |
messages.send |
групповой | сообщение в диалог (peer_id, message, опц. attachment) |
wall_post |
wall.post |
групповой | пост на стену (owner_id, message, опц. attachments) |
search |
newsfeed.search |
сервисный | поиск записей/упоминаний (q, count) |
Результат: content — pretty-JSON ответа, data — распарсенный response
(для композиции с visualize_tool). Групповой токен нужен с правами messages,
wall, photos, docs, market, groups. Читающие/поисковые методы
(newsfeed.search, wall.get, groups.search) недоступны групповым
токенам — для них нужен сервисный ключ (service_token_env).
5.18 shell_tool
Запустить команду CLI. Универсальный запуск внешней программы: команда, флаги,
рабочая папка и окружение фиксируются в YAML автором агента; LLM лишь
подставляет значения в input. В отличие от произвольного fs_read, LLM не
выбирает команду — он выбирает только аргументы по заданной JSON Schema.
kind: shell_tool
name: git_log
description: Показать последние коммиты репозитория.
command: git
args: ["log", "--oneline", "-n", "{{ input.limit | default(10) }}"]
cwd: /srv/agent-os # рабочая папка (по умолч. — папка сервера)
env:
GIT_PAGER: "cat" # доп. переменные окружения
stdin: "{{ input.text }}" # текст в stdin (опционально)
timeout_secs: 30 # жёсткий таймаут (по умолч. 30)
capture: both # stdout | stderr | both (по умолч.)
parse_json: false # распарсить stdout как JSON в data.parsed
parameters: { ... } # JSON Schema входа агента
| Поле | Обязат. | Описание |
|---|---|---|
kind |
да | shell_tool |
name |
да | имя для LLM |
description |
нет | описание для LLM |
command |
да | программа (шаблон MiniJinja над input) |
args |
нет | список аргументов (каждый — шаблон) |
cwd |
нет | рабочая папка (шаблон) |
env |
нет | доп. переменные окружения (значения — шаблоны) |
stdin |
нет | текст, подаваемый в stdin (шаблон) |
timeout_secs |
нет | таймаут (по умолч. 30) |
capture |
нет | какие потоки вернуть: stdout | stderr | both |
parse_json |
нет | распарсить stdout как JSON в data.parsed |
Команда наследует окружение сервера + env, выполняется с лимитом по времени.
Результат: content — захваченный вывод, success — нулевой код выхода,
data — { exit_code, stdout, stderr, parsed? }.
Все строковые поля — шаблоны MiniJinja над input. Если на сервере задан
logging.temp_dir, в шаблонах доступна переменная {{ temp_dir }} — scratch-
каталог текущей сессии, куда можно нагенерировать файл (см.
file_tool с источником temp).
5.19 workflow_tool
Запустить воркфлоу.
kind: workflow_tool
name: run_triage
description: Запустить воркфлоу триажа.
workflow: triage # имя воркфлоу по умолчанию
Запускает воркфлоу и возвращает его run id. Имя воркфлоу можно перекрыть
аргументом workflow; input — входной payload. Требует, чтобы в ядре был
подключён WorkflowService (делается при старте сервера). См.
12-workflows.
5.20 file_tool
Отправить файл пользователю. Отправляет пользователю файл (отчёт, документ,
экспорт данных) в виде скачиваемого блока file. Агент обычно не имеет
доступа к файловой системе, поэтому содержимое берётся из одного из источников:
kind: file_tool
name: send_file
description: Отправить файл пользователю.
max_bytes: 10485760 # макс. размер файла в байтах (по умолч. 10 МиБ)
| Аргумент | Описание |
|---|---|
name |
имя файла для скачивания (обязательно), напр. report.html |
mime |
MIME-тип (необязательно; выводится из расширения name) |
content |
содержимое строкой (markdown / HTML / CSV / JSON…) |
data |
любой JSON — сериализуется в файл (pretty JSON) |
path |
прочитать байты из локального файла (если агент может писать файлы) |
temp |
{ name } — прочитать файл, который другой инструмент записал в scratch-каталог сессии |
state |
{ key, scope?, path? } — значение из state store (БД). scope: session/user/agent (по умолч. резолв user → session → agent); path — точечный путь внутрь значения |
source |
{ tool, index, field, path } — результат другого инструмента в этой сессии. field: content (по умолч.)/data/visual; index: 0 = последний |
Источник выбирается по приоритету content → data → path → temp →
state → source. Пример отчёта, собранного из результата предыдущего
инструмента:
# вызвать: send_file { "name": "report.csv", "source": { "tool": "build_report" } }
LLM видит только компактную сводку в content; сами байты (base64) едут в
visual и доходят до веб-виджета (ссылка скачивания), Android и Telegram
(документ).
Временное хранилище (scratch) сессии
Если в конфигурации задан logging.temp_dir, ядро выделяет каждой сессии
scratch-каталог <temp_dir>/<session_id>/. Инструмент-генератор (например,
shell_tool, запускающий офисный CLI) пишет файл туда через
{{ temp_dir }}, а file_tool забирает его по имени:
# shell_tool: нагенерить .xlsx в scratch сессии
kind: shell_tool
name: export_xlsx
description: Сгенерировать отчёт в Excel.
command: libreoffice
args: ["--headless", "--convert-to", "xlsx", "--outdir", "{{ temp_dir }}", "{{ input.docx }}"]
# вызвать: send_file { "name": "report.xlsx", "temp": { "name": "report.xlsx" } }
Каталог удаляется при закрытии/истечении сессии.
5.21 office_tool
Движок-обёртка над OfficeCLI (один
самодостаточный бинарь, MS Office не нужен). При первом использовании бинарь
скачивается автоматически в data/officecli/ и проверяется по SHA-256;
далее он кешируется. Готовый файл пишется в scratch сессии и возвращается
блоком file (как у file_tool) — внешние shell_tool-обёртки не нужны.
kind: office_tool
name: make_docx
description: Собрать Word-документ из Markdown.
operation: create # create | fill | extract | convert | edit | merge
format: docx # docx | xlsx | pptx (для create/merge)
# template: templates/contract.docx # для fill: путь к шаблону (отн. YAML)
# binary: /path/to/officecli # опц. явный путь к бинарю
# download_url: "https://..." # опц. переопределение
# sha256: "..." # опц. (пусто = не проверять)
# auto_download: true # по умолч. true
# pdf_bin: soffice # fallback для PDF (если нет плагина)
# pdf_exporter: /path/to/officecli_pdf_exporter # опц. явный путь к плагину
# timeout_secs: 120 # таймаут одной команды
Операции
operation |
Что делает | Аргументы |
|---|---|---|
create |
собрать документ с нуля | name + content (docx, Markdown) / rows+columns или csv (xlsx) / slides (pptx) |
fill |
заполнить шаблон с плейсхолдерами {{key}} |
name + data (объект) или rows (массив → mail merge, результат — zip) |
extract |
прочитать документ текстом/CSV для LLM | temp/path + опц. mode (text/outline/annotated/issues/csv) |
convert |
экспорт в HTML/SVG/PDF | name (.html/.svg/.pdf) + temp/path |
edit |
применить правки set/add/remove/replace |
name + temp/path + ops: [{ action, path, type?, props?, find?, replace? }] |
merge |
объединить несколько документов в один | name + `files: [{ temp |
Плейсхолдеры шаблонов (fill)
В шаблоне используются двойные фигурные скобки {{key}} — в абзацах, таблицах,
колонтитулах и заголовках графиков. Заполнение — это officecli merge:
# вызвать: fill_contract { "name": "dogovor.docx", "data": { "client": "ООО Ромашка", "sum": "150000" } }
# вызвать (mail merge): fill_contract { "name": "dogovor.docx", "rows": [ {...}, {...} ] }
# → вернёт dogovor.zip с N заполненными файлами
Шаблон .docx с плейсхолдерами можно получить самому из Markdown:
make_docx → contract.md с текстом вида {{client}}.
Редактирование (edit)
edit копирует входной документ в выходной и применяет список правок (исходник
не меняется). Каждая правка — { action, path, ... }:
# вызвать: edit_doc { "name": "edited.docx", "temp": { "name": "in.docx" },
# "ops": [
# { "action": "replace", "path": "/body", "find": "ООО Старое", "replace": "ООО Новое" },
# { "action": "set", "path": "/body/p[1]/r[1]", "props": { "bold": true } },
# { "action": "add", "path": "/body", "type": "paragraph", "props": { "text": "Новый абзац" } },
# { "action": "remove", "path": "/body/p[3]" }
# ] }
Действия: set (свойства по --prop), add (элемент --type), remove,
replace (поиск/замена текста через --find/--replace). path — адрес
элемента OfficeCLI (/body/p[1], /Sheet1/A1, /slide[1]/shape[1], …).
Примеры (полный набор)
Готовый агент-«секретарь» лежит в config/agents/office/ — там же все эти
инструменты и шаблон договора templates/contract.docx. Ниже — выдержки.
1. create — документ с нуля
# tools/make_docx.yaml
kind: office_tool
name: make_docx
description: Собрать Word из Markdown.
operation: create
format: docx
// вызов: { "name": "report.docx", "content": "# Отчёт\n\nТекст..." }
# tools/make_xlsx.yaml
kind: office_tool
name: make_xlsx
description: Собрать Excel из таблицы.
operation: create
format: xlsx
// вызов: { "name": "price.xlsx", "columns": ["Name","Price"], "rows": [["Apple",3],["Banana",5]] }
2. fill — шаблон с {{key}} + mail merge
# tools/fill_contract.yaml
kind: office_tool
name: fill_contract
description: Заполнить договор данными.
operation: fill
format: docx
template: ../templates/contract.docx # путь отн. этого YAML
// один документ: { "name": "dogovor.docx", "data": { "client": "ООО Ромашка", "sum": "150000" } }
// mail merge: { "name": "dogovor.docx", "rows": [ { "client": "A" }, { "client": "B" } ] }
// → вернёт dogovor.zip с N заполненными файлами
3. extract — чтение (текст или CSV)
kind: office_tool
name: extract_text
description: Прочитать документ текстом.
operation: extract
// { "temp": { "name": "dogovor.docx" } } → текст
// { "temp": { "name": "price.xlsx" }, "mode": "csv" } → CSV
4. convert — HTML / SVG / PDF
kind: office_tool
name: convert_pdf
description: Экспорт в PDF.
operation: convert
// { "name": "out.html", "temp": { "name": "in.docx" } }
// { "name": "out.pdf", "temp": { "name": "in.docx" } } // плагин + headless Chromium
5. edit — точечные правки
kind: office_tool
name: edit_doc
description: Внести правки в документ.
operation: edit
// { "name": "out.docx", "temp": { "name": "in.docx" }, "ops": [
// { "action": "replace", "path": "/body", "find": "старое", "replace": "новое" } ] }
6. merge — объединить документы
kind: office_tool
name: merge_docs
description: Объединить документы в один.
operation: merge
format: docx # docx — склейка текста; xlsx — конкатенация строк
// { "name": "all.docx", "files": [ { "temp": { "name": "a.docx" } }, { "temp": { "name": "b.docx" } } ] }
Форматы и ограничения
createподдерживаетdocx(из Markdown),xlsx(из строк/CSV) иpptx(изslides: [{ title, bullets[] }]).convertдаётhtml,svgиpdf. Дляpdfдвижок использует экспортер-плагин (officecli_pdf_exporter) — отдельный бинарь, который OfficeCLI находит черезOFFICECLI_PLUGIN_EXPORTER_PDF. Плагин рендерит документ в HTML движком OfficeCLI, а затем печатает его в PDF headless Chromium-браузером. Если браузера нет, он скачивается автоматически (chrome-headless-shellиз Chrome for Testing) в~/.cache/agent-os/browser(Linux) /%LOCALAPPDATA%\agent-os\browser(Windows). Работает headless на Linux-сервере.- Если плагина нет,
convert pdfоткатывается наsoffice(LibreOffice) — путь к бинарю задаётся полемpdf_bin. - Сам OfficeCLI скачивается при первом вызове: нужен доступ к GitHub Releases
(или задайте
download_url/binary).
5.24 storage_tool
Доступ к внешнему хранилищу файлов: S3-совместимое объектное хранилище
(AWS S3, MinIO, Yandex Object Storage, Cloud.ru), WebDAV (Nextcloud,
ownCloud) и FTP/FTPS. Операции list / get / put / delete, скоуп —
опциональный prefix. Секреты — из env.
kind: storage_tool
name: upload_report
description: Выгрузить отчёт в объектное хранилище.
storage:
backend: s3 # s3 | webdav | ftp
endpoint: https://s3.example.com
bucket: reports
region: us-east-1
access_key_env: S3_ACCESS_KEY
secret_key_env: S3_SECRET_KEY
path_style: true # по умолч. true (MinIO-стиль)
prefix: uploads/ # опц. базовый префикс (скоуп агента)
operation: put # опц.: list | get | put | delete
Бэкенды
backend |
Поля | Примечание |
|---|---|---|
s3 |
endpoint, bucket, region, access_key_env, secret_key_env, path_style? |
любой S3-совместимый сервис |
webdav |
base_url, username_env, password_env |
base_url — корень файлов (напр. …/remote.php/dav/files/user/) |
ftp |
host, port?, username_env, password_env, tls? |
tls: none | explicit (FTPS, по умолч.) |
Операции
| operation | Назначение | Параметры |
|---|---|---|
list |
список файлов под префиксом | prefix (доп. суб-префикс) |
get |
скачать файл | key → текст в content + file-блок |
put |
загрузить файл | key + content/data/path/temp |
delete |
удалить файл | key |
Без operation операция выбирается аргументом operation (по умолчанию list).
get возвращает содержимое текстом (если это текст ≤ 20 тыс. символов) и всегда
file-блоком в visual; list возвращает массив {key, size, last_modified} в
data + таблицу.
5.25 calendar_tool
Чтение и управление Google Calendar от имени сервисного аккаунта (2-legged OAuth — JWT bearer, без интерактивного согласия). Движок сам обменивает ключ сервисного аккаунта на access-токен (с кешем по TTL) и вызывает Google Calendar API v3.
kind: calendar_tool
name: calendar
description: Читать и управлять календарём.
credentials_file: data/google-calendar/service_account.json # путь к JSON-ключу
# credentials_env: GOOGLE_SERVICE_ACCOUNT_JSON # или env с JSON-текстом (по умолч.)
# credentials: { ... } # или inline-объект (не рекомендуется)
calendar_id: petrochenko.pavel.a@gmail.com # дефолтный календарь (перекрывается аргументом)
| Поле | Описание |
|---|---|
credentials_file |
путь к JSON-ключу сервисного аккаунта (приоритетнее остальных) |
credentials_env |
имя env с JSON-текстом ключа (по умолч. GOOGLE_SERVICE_ACCOUNT_JSON) |
credentials |
inline-ключ (не рекомендуется — держите секреты в файле/env) |
calendar_id |
дефолтный id календаря (перекрывается аргументом calendar_id) |
Секреты не держат в YAML. Порядок разрешения ключа: credentials_file →
credentials → env credentials_env.
Действия (аргумент action):
| Действие | API-метод | Что делает |
|---|---|---|
list_calendars |
calendarList.list |
список календарей сервисного аккаунта |
list |
events.list |
события диапазона (time_min/time_max, max_results, q) |
get |
events.get |
одно событие (event_id) |
create |
events.insert |
создать событие (summary, start, end, location, description, attendees) |
update |
events.update |
изменить событие (event_id + те же поля) |
delete |
events.delete |
удалить событие (event_id) |
quick_add |
events.quickAdd |
создать событие из свободного текста (text) |
{ "action": "list", "time_min": "2026-09-07T00:00:00Z", "max_results": 20 }
{ "action": "create", "summary": "Созвон", "start": "2026-09-10T15:00:00+03:00", "end": "2026-09-10T16:00:00+03:00" }
{ "action": "quick_add", "text": "Ужин завтра в 19:00" }
start/end принимают строку RFC3339 (→ dateTime) или объект
{ dateTime, timeZone } / { date } (событие на весь день). Полное событие можно
передать объектом event. Generic-шлюз: method (в нотации ресурс.действие)
params(query) +body:
{ "method": "events.list", "params": { "timeMin": "2026-09-07T00:00:00Z" } }
{ "method": "calendars.insert", "body": { "summary": "Рабочий календарь" } }
Поддерживаемые методы: calendarList.list, events.list/get/insert/
update/delete/quickAdd, calendars.insert/delete, freebusy.query.
Результат: content — pretty-JSON ответа, data — распарсенный ответ (для
композиции с visualize_tool).
Настройка доступа
- Создайте сервисный аккаунт (или возьмите готовый JSON-ключ) и включите Google Calendar API в проекте (Cloud Console → API Library).
- Дайте сервисному аккаунту доступ к календарю: настройки календаря →
«Предоставить доступ» → добавьте
client_emailс правами «Изменение событий». - Укажите
calendar_id— обычно email владельца (name@gmail.com) илиxxx@group.calendar.google.com(поле «Идентификатор календаря» в настройках).
Нюанс: list_calendars у сервисного аккаунта может вернуть пустой список — у
него нет «своих» календарей, а расшаренные в calendarList не добавляются
автоматически. Работайте по calendar_id напрямую (задан в конфиге или
аргументе).
5.26 google_tool
Чтение и управление Google Drive / Sheets / Docs / Slides. Два режима
авторизации: сервисный аккаунт (2-legged OAuth / JWT) — подходит только для
чтения; и OAuth от имени пользователя — для чтения и записи (с квотой
реального аккаунта). Один экземпляр google_tool работает с одним сервисом
(поле service); для нескольких сервисов подключите несколько инструментов.
kind: google_tool
name: gdrive
description: Обзор и управление Google Drive.
service: drive # drive | sheets | docs | slides
auth: oauth # oauth (рекомендуется) | service_account
oauth:
client_id: 123-abc.apps.googleusercontent.com
client_secret_env: GOOGLE_OAUTH_CLIENT_SECRET
token_file: data/google-oauth/drive_token.json
# для service_account (только чтение):
# credentials_file: data/google-calendar/service_account.json
# scopes: ["https://www.googleapis.com/auth/drive.file"] # опц. переопределение
| Поле | Описание |
|---|---|
service |
целевой сервис: drive | sheets | docs | slides |
auth |
oauth (по умолчанию не задан — service_account) | service_account |
oauth.client_id / client_id_env |
OAuth client id (inline или env) |
oauth.client_secret / client_secret_env |
OAuth client secret (env) |
oauth.token_file |
файл, где хранится refresh-токен после authorize_code |
oauth.redirect_uri |
redirect URI (по умолчанию — OOB copy-paste) |
credentials_file / credentials_env / credentials |
ключ сервисного аккаунта (как у calendar_tool) |
scopes |
опц. переопределение OAuth-скоупов |
Авторизация пользователя (OAuth)
Разовый шаг, выполняется через сам инструмент:
- Вызовите действие
authorize— вернётся URL согласия. - Откройте URL, войдите в Google и разрешите доступ.
- Скопируйте код и вызовите
authorize_codeс полемcode— refresh-токен сохранится вtoken_file.
{ "action": "authorize" }
{ "action": "authorize_code", "code": "4/0A..." }
Дальше инструмент сам обновляет access-токен по refresh-токену.
Каждый сервис поддерживает generic-шлюз method (нотация ресурс.действие)
params/body, и набор удобных действийaction.
Действия по сервисам
Drive (service: drive):
| Действие | API-метод | Что делает |
|---|---|---|
list |
files.list |
список файлов (q, page_size) |
get |
files.get |
метаданные файла (file_id) |
create_folder |
files.create |
создать папку (name, опц. parents) |
upload |
files.create (multipart) |
загрузить файл (name, content, mime_type, parents) |
export |
files.export |
экспорт Google-файла в формат (file_id, mime_type, опц. name) |
download |
files.get?alt=media |
скачать содержимое файла (file_id, опц. name) |
delete |
files.delete |
удалить файл (file_id) |
export/download возвращают текст (text) для текстовых форматов, а бинарные
(PDF/DOCX/XLSX) — как base64 + файл в scratch-каталоге сессии (для file_tool).
Sheets (service: sheets):
| Действие | API-метод | Что делает |
|---|---|---|
create |
spreadsheets.create |
создать таблицу (title) |
get |
spreadsheets.get |
метаданные таблицы (spreadsheet_id) |
read |
spreadsheets.values.get |
прочитать диапазон (spreadsheet_id, range) |
write |
spreadsheets.values.update |
записать диапазон (spreadsheet_id, range, values) |
append |
spreadsheets.values.append |
дописать строки (spreadsheet_id, range, values) |
import |
values.update |
вписать CSV (csv) или массив (values) в диапазон |
export |
values.get |
выгрузить диапазон как csv или json (format) |
add_chart |
batchUpdate |
встроенный график (range, title, chart_type: COLUMN/BAR/LINE/PIE/AREA) |
Docs (service: docs):
| Действие | API-метод | Что делает |
|---|---|---|
create |
documents.create |
создать документ (title) |
import |
create + batchUpdate | создать документ с текстом (title, content) |
build |
create + batchUpdate | собрать документ из блоков (title, blocks) |
export |
documents.get |
извлечь текст документа (document_id) |
get |
documents.get |
сырой JSON документа (document_id) |
insert_text |
documents.batchUpdate |
вставить текст (document_id, text, опц. index) |
build собирает документ из структурированных блоков с стилями:
{ "action": "build", "title": "Отчёт", "blocks": [
{ "type": "heading", "text": "Раздел", "level": 1 },
{ "type": "paragraph", "text": "Жирный синий", "style": { "bold": true, "color": "#0000FF", "fontSize": 14, "align": "CENTER" } },
{ "type": "bullet", "items": ["a", "b"] },
{ "type": "numbered", "items": ["раз", "два"] },
{ "type": "table", "rows": [["Имя", "Значение"], ["alpha", 1]] },
{ "type": "image", "url": "https://…/img.png" },
{ "type": "page_break" }
] }
style поддерживает bold/italic/underline/strikethrough, color
(#RRGGBB), background_color (#RRGGBB), font (имя шрифта, напр. Arial,
Times New Roman), weight (400=обычный, 700=жирный), fontSize (pt),
align (START/CENTER/END/JUSTIFIED), lineSpacing.
Slides (service: slides):
| Действие | API-метод | Что делает |
|---|---|---|
create |
presentations.create |
создать презентацию (title) |
build |
create + batchUpdate | собрать презентацию из слайдов (title, slides) |
add_slide |
batchUpdate | добавить слайд (presentation_id, title, bullets) |
outline |
presentations.get |
упрощённый текстовый план слайдов |
export |
files.export |
экспорт в PDF (presentation_id, опц. mime_type) |
get |
presentations.get |
сырой JSON презентации |
{ "action": "build", "title": "Презентация", "slides": [
{ "title": "Титул", "bullets": ["пункт 1", "пункт 2"] },
{ "title": "Картинка", "image": { "url": "https://…/img.png" } }
] }
Универсальный батчинг запросов
Действие batch_update — универсальный примитив: передайте сырой список
requests и он применится к нужному ресурсу (document_id /
presentation_id / spreadsheet_id):
{ "action": "batch_update", "document_id": "<id>", "requests": [
{ "insertText": { "text": "hi\n", "location": { "index": 1 } } },
{ "updateTextStyle": { "range": { "startIndex": 1, "endIndex": 3 }, "textStyle": { "bold": true }, "fields": "*" } }
] }
Это escape-hatch для любой операции, не покрытой удобными действиями (тот же
эффект даёт method: documents.batchUpdate + body: {requests: [...]}).
Ограничения API
- Колонки (multi-column layout) в Docs API не поддерживаются — это только UI-фича.
- Таблицы в Slides API не поддерживает (только в UI) — используйте таблицы в Docs или Sheets.
- Рендер встроенного графика в PNG нет прямого API;
add_chartсоздаёт встроенный график, видимый в UI.
Примеры вызовов:
{ "action": "list", "q": "name contains 'report'", "page_size": 20 }
{ "action": "upload", "name": "notes.txt", "content": "hello", "mime_type": "text/plain", "parents": ["<folder_id>"] }
{ "action": "export", "file_id": "<id>", "mime_type": "application/pdf", "name": "report.pdf" }
{ "action": "import", "spreadsheet_id": "<id>", "range": "A1:C4", "csv": "a,b,c\n1,2,3\n" }
{ "action": "export", "document_id": "<id>" }
{ "action": "build", "title": "Отчёт", "blocks": [ ... ] }
Generic-шлюз (для нестандартных методов):
{ "method": "files.list", "params": { "q": "mimeType='application/vnd.google-apps.folder'" } }
{ "method": "spreadsheets.values.get", "spreadsheet_id": "<id>", "range": "Sheet1!A1:D10" }
{ "method": "documents.get", "document_id": "<id>" }
{ "method": "presentations.get", "presentation_id": "<id>" }
Поддерживаемые методы: files.list/get/create/delete/copy,
permissions.list/create, spreadsheets.create/get/values.get/
values.update/values.append/batchUpdate, documents.create/get/
batchUpdate, presentations.create/get/batchUpdate.
Результат: content — pretty-JSON ответа, data — распарсенный ответ.
Настройка доступа
- Включите нужные API (Drive / Sheets / Docs / Slides) в Cloud Console.
- Для OAuth-режима (запись): создайте OAuth client ID (тип «Desktop app»),
укажите
client_id/client_secret, пройдитеauthorize→authorize_code.
Важно про сервисный аккаунт. У него нет собственной квоты Drive — он не
может загружать/создавать файлы (storage quota exceeded / caller does not have permission) даже в расшаренных папках (владельцем файла всё равно
становится сервисный аккаунт). Поэтому для записи используйте OAuth-режим;
сервисный аккаунт подходит только для чтения расшаренных файлов.
{ "action": "upload", "name": "report.csv", "content": "a,b\n1,2", "mime_type": "text/csv" }
{ "action": "create", "title": "Отчёт" }
5.26.1 yandex_tool
Работа с сервисами Яндекса (Диск и Календарь) от имени реального
Яндекс-аккаунта через 3-legged OAuth2. У Яндекса нет сервисных аккаунтов, поэтому
авторизация всегда пользовательская: разовый шаг authorize → authorize_code
сохраняет refresh-токен в token_file, дальше access-токены обновляются сами.
Один экземпляр yandex_tool работает с одним сервисом (поле service).
kind: yandex_tool
name: yandex_disk
description: Обзор и управление Яндекс.Диском.
service: disk # disk | calendar
oauth:
client_id: "…" # id приложения (inline или client_id_env)
client_secret_env: YANDEX_OAUTH_CLIENT_SECRET
token_file: data/yandex-oauth/disk_token.json
# email: you@yandex.ru # обязателен для calendar (путь CalDAV)
# scopes: ["cloud_api:disk.read", ...] # опц. переопределение
| Поле | Описание |
|---|---|
service |
целевой сервис: disk | calendar |
email |
Яндекс-email аккаунта — обязателен для calendar (путь …/calendars/{email}/events-default/) |
calendar |
имя коллекции календаря для CalDAV (по умолч. events-default) |
oauth.client_id / client_id_env |
OAuth client id (inline или env) |
oauth.client_secret / client_secret_env |
OAuth client secret (env; для публичных приложений можно опустить) |
oauth.token_file |
файл, где хранится refresh-токен после authorize_code |
oauth.redirect_uri |
redirect URI — должен совпадать с Callback URL приложения (для приложений «доступ к API» это https://oauth.yandex.ru/verification_code) |
scopes |
опц. переопределение OAuth-скоупов |
Авторизация (разовый шаг, через сам инструмент):
{ "action": "authorize" }
{ "action": "authorize_code", "code": "…" }
Диск (service: disk)
Базовый URL https://cloud-api.yandex.net/v1/disk, заголовок
Authorization: OAuth <token> (не Bearer). Действия:
| Действие | API-метод | Что делает |
|---|---|---|
info |
GET /disk |
информация о Диске (объём, лимиты) |
list |
GET /resources |
содержимое папки (path, по умолч. /; limit/offset/sort) |
get |
GET /resources |
метаданные ресурса (path) |
create_folder |
PUT /resources |
создать папку (path) |
delete |
DELETE /resources |
удалить (path, опц. permanently) |
copy |
POST /resources/copy |
скопировать (from, path, опц. overwrite) |
move |
POST /resources/move |
переместить (from, path, опц. overwrite) |
upload |
GET /resources/upload → PUT href |
загрузить файл (path, content) |
download |
GET /resources/download → GET href |
скачать файл (path, опц. name) |
publish / unpublish |
`PUT /resources/publish | unpublish` |
files |
GET /resources/files |
плоский список всех файлов (limit/offset) |
last_uploaded |
GET /resources/last-uploaded |
последние загруженные файлы |
upload выполняет двухшаговую загрузку (сначала получает временный href от
API, затем PUT туда содержимого). download так же двухшаговый и возвращает
текст (text) для текстовых форматов, а бинарные — как base64 + файл в
scratch-каталоге сессии.
Календарь (service: calendar)
У Яндекса нет публичного REST API Календаря — он работает по протоколу
CalDAV (RFC 4791) на https://caldav.yandex.ru. Токен передаётся тем же
заголовком Authorization: OAuth <token>; для REPORT/PROPFIND нужен
Content-Type: text/xml, для событий — text/calendar. Требуется поле email
(по нему строится путь …/calendars/{email}/events-default/).
| Действие | CalDAV | Что делает |
|---|---|---|
list_calendars |
— | дефолтный календарь (у Яндекса он один) |
list |
REPORT (calendar-query) |
события диапазона (from/to RFC3339, опц. limit) |
get |
GET …/{uid}.ics |
одно событие (uid) |
create |
PUT …/{uid}.ics |
создать событие (summary, start, end, location, description; uid авто-генерится) |
update |
PUT …/{uid}.ics |
перезаписать событие (uid + поля) |
delete |
DELETE …/{uid}.ics |
удалить событие (uid) |
start/end принимают строку RFC3339 (→ UTC), строку YYYY-MM-DD (событие на
весь день) или объект { dateTime, timeZone }. Событие идентифицируется полем
uid (или алиасом event_id).
{ "action": "list", "from": "2026-09-01T00:00:00Z" }
{ "action": "create", "summary": "Созвон", "start": "2026-09-10T15:00:00+03:00", "end": "2026-09-10T16:00:00+03:00" }
{ "action": "delete", "uid": "agent-os-abc123" }
Generic-шлюз
Для нестандартных вызовов Диска: method + params (query) + body.
Примеры: resources, resources.download, resources.upload, resources.copy,
resources.move, resources.files.
{ "action": "list", "path": "/documents" }
{ "action": "upload", "path": "/report.csv", "content": "a,b\n1,2" }
{ "action": "create", "summary": "Созвон", "start": "2026-09-10T15:00:00+03:00", "end": "2026-09-10T16:00:00+03:00" }
{ "method": "resources", "params": { "path": "/" } }
Настройка доступа
- Зарегистрируйте приложение на oauth.yandex.ru (тип «Веб-сервисы» для client_secret или «Для доступа к API»).
- Укажите нужные права: для Диска —
cloud_api:disk.read/write/info, для Календаря —calendar:all. redirect_uri(oauth.redirect_uri) обязан совпадать с Callback URL приложения. Для приложений «для доступа к API» это фиксированное значениеhttps://oauth.yandex.ru/verification_code.- Пройдите
authorize→authorize_code, refresh-токен сохранится вtoken_file.
5.27 vision_tool
Анализ изображений vision-моделью (deepseek-v4-flash-vision-exp): OCR,
описание, ответ на вопрос по картинке. Тул принимает одну или несколько
картинок, отдаёт их модели и возвращает текст. Токены (включая токены картинок)
списываются с бюджета вызывающего агента через LLM-сервис ядра.
kind: vision_tool
name: vision
description: Прочитать текст / описать / ответить на вопрос по картинке(ам).
model: vision # именованная модель из server.yaml → models:
prompt: "Transcribe all text visible in the image(s) verbatim, in reading order."
detail: auto # low | high | original | auto
max_tokens: 2048
| Поле | Описание |
|---|---|
model |
именованная модель (provider) из server.yaml → models: (по умолч. vision) |
prompt |
дефолтный промпт (перекрывается аргументом prompt) |
detail |
low | high | original | auto |
max_tokens |
лимит ответа (по умолч. 2048) |
Аргументы: images (массив строк, обязателен), prompt?, detail?.
Каждый элемент images — http(s) URL, data:image/...;base64,... или путь к
локальному файлу (абсолютный или относительно scratch-каталога сессии; читается
и кодируется в base64). Пример вызова:
{ "images": ["https://example.com/shot.png"], "prompt": "Что за ошибка на скрине?" }
Результат — content с ответом модели.
5.28 request_attachment
Запрос вложения у пользователя прямо в ходе работы агента (не кнопками виджета):
агент вызывает тул, ядро шлёт в канал событие input_request, канал показывает
подсказку, пользователь прикрепляет файл / делает скриншот / фото — и ход
продолжается. Загруженный файл попадает в scratch-каталог сессии, а тул возвращает
его имя — дальше его можно прочитать (vision_tool по имени, file_tool и т.п.).
Работает в интерактивных каналах: веб-чат (виджет показывает карточку-подсказку), Telegram, VK и Яндекс Мессенджер (бот шлёт сообщение «пришлите файл/фото», ответ пользователя с медиа резолвит запрос). В batch-каналах (cron/email/webhook) UI нет — вызов завершится таймаутом.
kind: request_attachment
name: request_image
description: Попросить пользователя прислать файл, скриншот или фото.
prompt: "Пожалуйста, прикрепите файл, сделайте скриншот или фото."
timeout_secs: 300
| Поле | Описание |
|---|---|
prompt |
дефолтный текст, показываемый пользователю (перекрывается аргументом description) |
timeout_secs |
сколько ждать ответа (по умолч. 300) |
Аргументы: kind (file | screenshot | photo), description?, timeout_secs?.
Результат — content с JSON вида
{"kind":"screenshot","files":[{"name":"screenshot-....png","mime":"image/png","size":12345}]}.
5.28.1 oauth_connect
Просит пользователя авторизовать доступ к коннектору (OAuth-защищённому внешнему
API — Google Drive, Яндекс.Диск и т.п., конфиг connectors: в §3). Агент вызывает
тул, ядро шлёт в канал событие input_request с authorization URL, пользователь
открывает его и даёт согласие; callback /v1/connectors/callback обменивает code,
сохраняет токен (per-user, зашифрован) и резолвит запрос — ход продолжается.
kind: oauth_connect
name: oauth_connect
description: Попросить пользователя авторизовать доступ к коннектору.
timeout_secs: 300
Аргументы: connector (имя коннектора), timeout_secs?. Результат — JSON
{"connector":"gdrive","granted":true}.
5.28.2 connector_request
Аутентифицированный HTTP-запрос через коннектор от имени пользователя (токен ищется по user_id, при протухании — авто-refresh через refresh_token).
kind: connector_request
name: connector_request
description: Сделать авторизованный запрос через коннектор.
Аргументы: connector, method (GET/POST/PATCH/DELETE/…), url,
body? (JSON/текст). Результат — тело ответа (content); при ошибке —
Error: <status>: <body>.
5.28.3 await_event
Приостановить ход и дождаться внешнего события: коллбэка POST /v1/events/callback
(источник webhook) или таймера (источник cron). Это обобщённый примитив
«подожди, пока снаружи что-то произойдёт» — в отличие от request_attachment
(ждёт файл) и oauth_connect (ждёт OAuth), здесь ожидается произвольный внешний
триггер.
kind: await_event
name: wait_payment
description: Дождаться подтверждения оплаты по correlation id.
timeout_secs: 600
event:
source: webhook # webhook (default) | cron
id_pointer: /object/id # где id в теле коллбэка (default /id)
# id_query: payment_id # либо query-параметр (взаимоисключает id_pointer)
| Поле | Описание |
|---|---|
event.source |
webhook (по умолч.) — ждать коллбэк; cron — таймер |
event.id_pointer |
JSON-pointer → correlation id в теле коллбэка (default /id) |
event.id_query |
имя query-параметра (взаимоисключает id_pointer) |
event.delay_secs |
для source: cron — сколько секунд подождать |
timeout_secs |
сколько ждать события (по умолч. 600) |
source: webhook: аргумент event_id (обязательный) — id, которого ждём. Пока
ход висит, в канал уходит input_request; внешняя система шлёт
POST /v1/events/callback { ... } (auth — events.token_env), ядро сопоставляет
коллбэк по id (через event.id_pointer/id_query) и резолвит ход. Результат —
{"event_id":"...","payload":{...}}.
source: cron: аргумент delay_secs — просто подождать N секунд и продолжить.
5.28.4 async_action
Полный декларативный асинхронный флоу start → prompt → suspend → callback → resume: сначала HTTP-запрос создаёт ресурс (платёж и т.п.), затем из его ответа
извлекаются correlation id и URL для показа, ход приостанавливается до коллбэка.
kind: async_action
name: sbp_payment
description: Принять оплату по СБП и дождаться подтверждения.
parameters:
type: object
properties: { amount: { type: string } }
required: [amount]
start: # поля как у rest_tool (method/url/json/headers/oauth2/sign)
method: POST
url: "https://api.yookassa.ru/v3/payments"
json: { amount: { value: "{{ amount }}", currency: "RUB" }, capture: true }
headers:
Authorization: "Basic {{ (env_var('YOOKASSA_SHOP_ID') ~ ':' ~ env_var('YOOKASSA_SECRET_KEY')) | base64 }}"
prompt:
message: "Оплатите по QR:"
url_pointer: /confirmation/confirmation_url
resolve:
id_pointer: /id
callback:
id_pointer: /object/id
timeout_secs: 600
| Поле | Описание |
|---|---|
start |
HTTP-запрос-инициатор (поля как у rest_tool/site_tool) |
prompt.message |
текст, показываемый пользователю |
prompt.url_pointer |
JSON-pointer → URL в ответе start (канал показывает кнопку/ссылку) |
resolve.id_pointer |
JSON-pointer → correlation id в ответе start |
callback.id_pointer / callback.id_query |
где id в коллбэке (default /id) |
Флоу: start выполняется движком site_tool (и его рендером шаблонов/авторизацией),
из ответа извлекаются id/url, дальше — тот же suspend/resume, что у await_event
(роут /v1/events/callback). Результат — {"event_id":"...","payload":{...}}.
5.28.5 show_link
Показать пользователю ссылку кнопкой (в виджете — по нажатию открывается окно со ссылкой; в мессенджерах — ссылка в сообщении/кнопке). Сам по себе ничего не ждёт и не делает — просто презентует URL.
kind: show_link
name: open_link
description: Показать пользователю ссылку.
wait: false # true — показать «Открыть» + «Готово» и ждать подтверждения
timeout_secs: 300
| Поле | Описание |
|---|---|
wait |
false (по умолч.) — показать и вернуть управление; true — ждать подтверждения пользователя («Готово») |
timeout_secs |
сколько ждать подтверждения (только при wait: true) |
Аргументы: url (обязательный), message?, wait? (перекрывает конфиг).
Результат — {"shown":true} (или {"shown":true,"confirmed":true} при wait: true).
5.29 image_tool
Обработка изображений прямо на сервере (без vision-модели): обрезка, изменение
размера, ч/б, поворот/отражение, яркость/контраст/размытие и конвертация формата.
Источник — http(s) URL, data: URL, локальный путь (абсолютный или относительно
scratch-каталога сессии) или файл из scratch через temp: { name }. Операции
подаются батчем в ops и применяются по порядку.
kind: image_tool
name: image_edit
description: Обрезать / изменить размер / ч/б / повернуть / отконвертировать картинку.
max_bytes: 26214400 # лимит размера входного/выходного файла (по умолч. 25 MiB)
| Операция | Аргументы | Эффект |
|---|---|---|
crop |
{ x, y, width, height } или { left, top, right, bottom } |
вырезать прямоугольник |
resize |
{ width, height, fit?, filter? } |
fit: contain (по умолч.) / exact / cover; filter: nearest / triangle / catmullrom / gaussian / lanczos3 |
grayscale |
— | обесцветить |
rotate |
{ degrees } (90 / 180 / 270) |
повернуть без потерь |
flip |
{ direction } (horizontal / vertical / both) |
отразить |
brightness |
{ value } |
прибавить к пикселям (отрицательное — затемнить) |
contrast |
{ factor } |
1.0 = без изменений |
blur |
{ sigma } |
гауссово размытие |
format |
{ format, quality? } |
конвертация в png / jpeg / webp / gif / bmp / tiff; quality (1–100) для jpeg |
info |
— | записать текущие размеры/формат (без изменений) |
Аргументы вызова: input (строка — URL / data: URL / путь) или temp: { name },
ops (массив операций), output? (имя файла для записи в scratch), send?
(явно управляет отправкой: по умолчанию false, когда задан output — только
в scratch; иначе true).
Вывод. Результат кодируется в байты и:
- пишется в scratch-каталог сессии, если задан
output(доступен потом черезtemp: { name },file_toolи т.п.); - отдаётся пользователю как
file-блок (base64), еслиsend: true— картинка показывается встроенным превью везде: веб-виджет (<img>), Telegram, VK и Яндекс Мессенджер (фото, дляimage/jpeg|png|gif|webp; остальные форматы уходят документом), Android (инлайн-превью + «Открыть»/«Сохранить»). Можно и то, и другое одновременно, либо только одно из двух.
Без ops тул возвращает только метаданные картинки (ширина/высота/формат/размер).
Пример (URL → кроп → ресайз → ч/б → jpeg, отдать пользователю и сохранить в scratch):
{
"input": "https://example.com/photo.jpg",
"ops": [
{ "op": "crop", "x": 0, "y": 0, "width": 800, "height": 600 },
{ "op": "resize", "width": 400, "height": 400, "fit": "cover" },
{ "op": "grayscale" },
{ "op": "format", "format": "jpeg", "quality": 85 }
],
"output": "avatar.jpg",
"send": true
}
5.30 mcp_tool
Подключить один инструмент внешнего MCP-сервера (Model Context Protocol).
Агент хостит MCP-инструменты, но сам MCP-сервером не является — mcp_tool
выступает клиентом, который по полю tool: вызывает конкретный тул на сервере.
Транспорты:
stdio— локальный процесс (command+args+env), newline-delimited JSON-RPC;http/sse— Streamable HTTP (POST JSON-RPC, ответapplication/jsonилиtext/event-stream;sse— алиасhttp).
description и parameters (JSON Schema) берутся из tools/list сервера, если
не перекрыты в YAML, поэтому LLM видит ровно ту схему, которую декларирует
сервер. Схема подтягивается на этапе загрузки конфига (а не в рантайме); если
сервер недоступен при загрузке — регистрируется fallback-схема, а ошибка
подключения вернётся уже в момент вызова.
kind: mcp_tool
name: read_file # имя, под которым тул виден агенту
description: Прочитать файл # необязательно — по умолчанию из схемы сервера
server:
transport: stdio # stdio | http | sse
command: npx # только stdio
args: ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
env: {} # только stdio, доп. переменные для процесса
# — или удалённый сервер —
# transport: http
# url: https://example.com/mcp
# headers: { Authorization: "Bearer ${MCP_TOKEN}" }
timeout_secs: 30
tool: read_file # имя тула на MCP-сервере (обязательно)
parameters: {} # необязательное перекрытие JSON Schema
ui: {} # необязательный UI-конфиг
# arguments: '{ "path": "{{ input.path }}", "encoding": "utf-8" }'
| Поле | Обязат. | Описание |
|---|---|---|
kind |
да | mcp_tool |
name |
да | локальное имя тула для LLM |
server |
да | конфиг сервера (см. ниже) |
tool |
да | имя тула на MCP-сервере |
description |
нет | перекрытие описания (иначе из tools/list) |
parameters |
нет | перекрытие JSON Schema (иначе из tools/list) |
arguments |
нет | шаблон аргументов вызова (см. ниже) |
ui |
нет | UI-конфиг (иконки, шаблоны вывода) |
Поля блока server:
| Поле | Транспорт | Описание |
|---|---|---|
transport |
— | stdio | http | sse |
command |
stdio | программа (обязательно) |
args |
stdio | аргументы |
env |
stdio | доп. переменные окружения процесса |
url |
http/sse | URL MCP-эндпоинта (обязательно) |
headers |
http/sse | доп. заголовки запроса |
timeout_secs |
— | таймаут запроса/рукопожатия (по умолч. 30) |
${ENV_VAR} в command, args, env, url и headers раскрывается из
окружения процесса — секреты не зашиваются в YAML.
Шаблонизация вызова. Без arguments в tools/call передаётся сырой input
от LLM. Поле arguments — строка-шаблон MiniJinja, которая рендерится в JSON
документ; в скоупе доступны input, temp_dir, session_id, user_id,
template. Так автор агента может инжектить фиксированные поля, перемапливать
вход LLM на схему сервера или подставлять идентификатор пользователя:
arguments: '{ "query": "{{ input.query }}", "user": "{{ user_id }}", "limit": 10 }'
Соединения к одному серверу переиспользуются (пул по server), поэтому несколько
mcp_tool, ссылающихся на один сервер, держат один живой процесс / HTTP-сессию.