工具 — 计算与操作

🔵 执行具体操作的引擎:脚本、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 无模板的内联指令
tools 子代理的工具名称(覆盖模板)
budget { max_per_turn, max_per_minute, max_total } 的 token 上限
output_schema 结构化结果的 JSON Schema(子代理以 job_done 结束;校验后的 payload 位于 data)
params 作为 template_vars 传递给子代理的字符串键值对(其工具可通过 ToolContext 看到),例如用于 code 模块的 code_root
allow_params LLM 可在调用参数 params 中设置的键(留空 = 仅静态)

运行时参数:task(必填),可选 template/instructions/params。


ask_user

向用户展示表单(一次多个问题)并返回结构化回答 { "answers": { "<id>": <value> } }。流程会阻塞,直到收到回答或超时。

类型:text、textarea、number、select(单选)、multiselect(复选框)、confirm(是/否)、date。select/multiselect 具有 options: [...];allow_other: true 会添加自由填写的「自定义选项」。

{ "title": "Настройки проекта",
  "questions": [
    { "id": "os", "type": "select", "label": "ОС?", "options": ["Linux","macOS","Windows"], "allow_other": true },
    { "id": "features", "type": "multiselect", "label": "Фичи", "options": ["a","b"] },
    { "id": "proceed", "type": "confirm", "label": "Продолжить?" }
  ] }

该组件渲染原生控件;在即时通讯工具中问题以文本形式显示。模块 agent_tools。


notify_tool

通过通知渠道吸引用户注意。级别 level 决定坚持程度:silent — 静默行,notify — 声音,alert — heads-up,alarm/call — 重复直到确认(在 Android 上 — 闹钟 / 来电)。channels — 任意 sink(如同 cron 中的 notify:);留空 = 事件保存到 message store。

kind: notify_tool
name: notify
description: Привлеки внимание пользователя.
level: alert
require_ack: false
# channels: [ { type: yandex_messenger, chat_id: "user@ya" } ]

调用参数:title?、body(必填)、level?、require_ack?。模块 agent_tools。


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 内联密码或环境变量名
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 存放社区 token 的环境变量名(群组操作:send_message、wall_post、通用网关)
service_token_env 存放服务密钥的环境变量名——用于群组 token 无法访问的搜索/读取方法(search)
api_version VK API 版本(默认 5.199)
owner_id wall_post 的默认所有者(负数 = 群组)

两种调用模式。通用网关——任意 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 方法 Token 作用
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 组合)。群组 token 需要具备 messages、wall、photos、docs、market、groups 权限。读取/搜索方法(newsfeed.search、wall.get、groups.search)群组 token 无法访问——它们需要服务密钥(service_token_env)。


5.17.1 ym_tool

通过 Yandex Messenger(Yandex 360)的 Bot API 以机器人身份发送消息和操作聊天——channel.yandex_messenger 渠道的输出「孪生」。

kind: ym_tool
name: yandex_messenger
description: Отправить сообщение в Яндекс Мессенджер.
token_env: YANDEX_MESSENGER_BOT_TOKEN  # env с токеном бота (по умолч.)
default_chat_id: ivan                  # опц.: логин или id чата по умолчанию
字段 描述
token_env 存放机器人 OAuth token 的环境变量名(默认 YANDEX_MESSENGER_BOT_TOKEN);token 在 Yandex 360 →「Messenger 中的机器人」中签发
default_chat_id 默认接收者:登录名(个人聊天)或带斜杠的群组/频道 id /

接收者在参数中指定:login(个人聊天)、chat_id(群组/频道)或 to(登录名,或带斜杠的聊天 id /);否则取 default_chat_id。

操作 作用
send 向聊天发送文本(text;markdown: true 将 CommonMark 转换为 Messenger 标记)
send_markdown 与 send 相同,带 markdown: true
send_file 文件文档(file — 路径,base64 或 content;name、mime)
send_image 向信息流发送图片(file/base64/content)
send_typing 显示「正在输入…」
get_updates 获取更新(offset、limit),返回 updates 和 next_offset
get_file 通过 file_id 下载文件(文本 — 内联,二进制 — base64 + 存入会话草稿)
{ "action": "send", "login": "ivan", "text": "Привет!" }
{ "action": "send", "chat_id": "0/0/4f24b544", "text": "**Отчёт** готов", "markdown": true }
{ "action": "get_updates", "offset": 0 }

结果:content — pretty-JSON,data — 结构化响应(发送时为 { "sent": n, "recipient": "..." })。


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 是 程序(基于 input 的 MiniJinja 模板)
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? }。

所有字符串字段都是基于 input 的 MiniJinja 模板。如果服务器上设置了 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 块的形式向用户发送文件(报告、文档、 数据导出)。Agent 通常没有文件系统访问权限,因此内容取自以下来源之一:

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 从本地文件读取字节(如果 Agent 能写文件)
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 并到达 Web 组件(下载链接)、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(数组 → 邮件合并,结果为 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]、…)。

示例(完整集合)

现成的“秘书”Agent 位于 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}} 的模板 + 邮件合并

# 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" } } ] }

格式与限制


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 以文本形式返回内容(如果是 ≤ 2 万字符的文本)并且始终 以 file 块形式返回在 visual 中;list 返回 {key, size, last_modified} 数组到 data + 表格。


5.25 calendar_tool

以服务账号身份读取和管理 Google Calendar(2-legged OAuth —— JWT bearer,无需交互式同意)。引擎自行将服务账号密钥 换取 access token(按 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 包含密钥 JSON 文本的 env 名称(默认 GOOGLE_SERVICE_ACCOUNT_JSON)
credentials 内联密钥(不推荐——请将密钥保存在文件/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 对象传递。通用网关:method(以 ресурс.действие 表示法)

{ "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 组合)。

配置访问权限

  1. 创建服务账号(或使用现成的 JSON 密钥)并在项目中启用 Google Calendar API(Cloud Console → API Library)。
  2. 授予服务账号对日历的访问权限:日历设置 → “共享” → 添加 client_email 并赋予“更改事件”权限。
  3. 指定 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(内联或 env)
oauth.client_secret / client_secret_env OAuth client secret(env)
oauth.token_file 在 authorize_code 之后存储 refresh token 的文件
oauth.redirect_uri redirect URI(默认——OOB 复制粘贴)
credentials_file / credentials_env / credentials 服务账号密钥(同 calendar_tool)
scopes 可选的 OAuth 作用域覆盖

用户授权(OAuth)

一次性步骤,通过工具本身执行:

  1. 调用 authorize 操作——将返回同意 URL。
  2. 打开 URL,登录 Google 并授权访问。
  3. 复制代码并调用 authorize_code,传入 code 字段——refresh 令牌 将保存到 token_file。
{ "action": "authorize" }
{ "action": "authorize_code", "code": "4/0A..." }

之后工具会自动通过 refresh 令牌刷新 access 令牌。

每个服务都支持 通用网关 method(表示法 ресурс.действие)

各服务的操作

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": "*" } }
] }

这是针对便捷操作未覆盖的任何操作的逃生通道(method: documents.batchUpdate + body: {requests: [...]} 也能达到同样效果)。

API 限制

调用示例:

{ "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": [ ... ] }

通用网关(用于非标准方法):

{ "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 —— 解析后的响应。

配置访问权限

  1. 在 Cloud Console 中启用所需的 API(Drive / Sheets / Docs / Slides)。
  2. 对于 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

以真实 Yandex 账号身份,通过 3-legged OAuth2 操作 Yandex 服务(Disk 和 Calendar)。Yandex 没有服务账号,因此 授权始终是用户级的:一次性步骤 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 Yandex 账号邮箱——对 calendar 必填(路径 …/calendars/{email}/events-default/)
calendar CalDAV 的日历集合名称(默认 events-default)
oauth.client_id / client_id_env OAuth client id(内联或环境变量)
oauth.client_secret / client_secret_env OAuth client secret(环境变量;公开应用可省略)
oauth.token_file 在 authorize_code 之后存储 refresh 令牌的文件
oauth.redirect_uri redirect URI——必须与应用的回调 URL 一致(对于「API 访问」类应用为 https://oauth.yandex.ru/verification_code)
scopes 可选:覆盖 OAuth 作用域

授权(一次性步骤,通过工具本身完成):

{ "action": "authorize" }
{ "action": "authorize_code", "code": "…" }

Disk(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 执行两步上传(先向 API 获取临时 href, 然后 PUT 内容到那里)。download 同样是两步的,对于文本格式返回 文本(text),而二进制格式则返回 base64 + 会话 scratch 目录中的文件。

日历(service: calendar)

Yandex 没有公开的日历 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 — 默认日历(Yandex 只有一个)
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" }

通用网关

对于磁盘的非标准调用: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": "/" } }

配置访问权限

  1. 在 oauth.yandex.ru 注册应用 (需要 client_secret 时选「Web 服务」类型,或选「用于 API 访问」)。
  2. 指定所需权限:对于磁盘 —— cloud_api:disk.read / write / info, 对于日历 —— calendar:all。
  3. redirect_uri(oauth.redirect_uri)必须与应用的回调 URL 一致。 对于「用于 API 访问」的应用,这是固定值 https://oauth.yandex.ru/verification_code。
  4. 完成 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 来自 server.yaml → models: 的命名模型(provider)(默认 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 和 Yandex Messenger(机器人发送消息「请发送文件/照片」, 用户带媒体的回复会解析该请求)。在批处理频道(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?。

结果 —— 带有如下 JSON 的 content {"kind":"screenshot","files":[{"name":"screenshot-....png","mime":"image/png","size":12345}]}。

5.28.1 oauth_connect

请求用户授权访问连接器(受 OAuth 保护的外部 API —— Google Drive、Yandex.Disk 等,配置 connectors: 见 §3)。代理调用 工具,内核向频道发送事件 input_request,其中包含 authorization URL,用户 打开它并给予同意;回调 /v1/connectors/callback 交换 code, 保存令牌(按用户,加密)并解析请求 —— 流程继续。

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_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(默认 /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 → 响应 start 中的 URL(通道显示按钮/链接)
resolve.id_pointer JSON-pointer → 响应 start 中的 correlation id
callback.id_pointer / callback.id_query 回调中 id 的位置(默认 /id)

流程:start 由引擎 site_tool 执行(及其模板渲染/授权), 从响应中提取 id/url,之后是与 await_event 相同的 suspend/resume (路由 /v1/events/callback)。结果是 {"event_id":"...","payload":{...}}。

5.28.5 show_link

以按钮形式向用户展示链接(在 widget 中 —— 点击后打开带链接的窗口; 在即时通讯工具中 —— 消息/按钮中的链接)。其本身不等待 也不做任何事 —— 只是呈现 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}(或在 wait: true 时为 {"shown":true,"confirmed":true})。

5.28.6 escalate_to_operator

将对话转交给人工操作员(代理发起的升级)。代理 调用该工具,内核开启升级并向配置的通道中的操作员 发送卡片(approval.operator_notify 中的 server.yaml —— Yandex Messenger / Telegram / webhook)。操作员输入 /accept,与 用户交流并通过命令 /release 结束;当空闲超过 timeout_secs 时,控制权带着 timeout_message 返回给代理。钩子 escalate 也有同样的 机制(参见钩子)。

kind: escalate_to_operator
name: escalate_to_operator
description: Передать диалог живому оператору.
contact: |
  📞 +7 (383) 363-40-37
  ✉️ priem@nsu.ru
connecting_message: "Соединяю вас с оператором, пожалуйста, подождите…"
unavailable_message: "Оператор сейчас недоступен.\n{contact}"
context_messages: 12
字段 描述
contact 当操作员不可用时,代理交给用户的联系方式
connecting_message 开启升级时给用户的消息
unavailable_message 给不可用操作员的文本;{contact} 从 contact 代入
context_messages 将最近多少条会话消息附到操作员卡片上(0 = 不带历史)

参数:reason(off_topic | empty_answer | user_requested | other)、 question?。结果是带 JSON 的 content {"status":"escalated","request_id":"…","message":"…"} 或 {"status":"unavailable","contact":"…"}(此时代理自行给出联系方式)。 在交互式通道中工作(web widget、Telegram、VK、Yandex Messenger); 操作员的回复会送达用户所在的通道(web —— 同一个 SSE 流)。

操作员通道

卡片会发送到 config/server.yaml → approval.operator_notify 中的通道 (与操作审批相同的列表 —— 参见 审批)。为空 = 不通知操作员。

# config/server.yaml
approval:
  operator_notify:
    - type: yandex_messenger
      chat_id: "pawelpetrochenko"      # логин оператора; для группового чата — id со слэшем
      token_env: YANDEX_MESSENGER_BOT_TOKEN
    - type: telegram
      chat_id: -100123456789            # приватный чат или группа операторов
      token_env: TG_OPERATOR_TOKEN
    - type: webhook
      url: https://ops.example.com/escalations
      token_env: OPS_WEBHOOK_TOKEN      # необязательно

密钥仅通过 token_env(来自 .env 的变量),不写在 YAML 中。

通道 卡片投递 操作员如何回复
yandex_messenger sendText 到私聊/chat_id 在聊天中输入文本:/accept、消息、/release
telegram 带 inline 按钮“✅ 接手处理” / “↩️ 退回给机器人”的卡片 按钮或文本 /accept、/release
webhook POST 升级事件的 JSON(bearer 来自 token_env) 仅通知;回复 —— 通过即时通讯工具

操作员命令:/accept [id] —— 接手对话;/release [id] (以及 /agent、!bot)—— 将控制权交还给代理;任何其他文本 都会发给用户。操作员的发言会投递到用户的通道 (web —— 同一个 SSE 流)。当空闲超过 timeout_secs 时,升级 关闭,并向用户发送 timeout_message。

审批和升级共用一个 approval.operator_notify:同一个机器人 服务两者,共用 long-poll getUpdates。如果操作员之前给 机器人写过消息 —— 卡片会发到同一个聊天中。

5.29 image_tool

直接在服务器上处理图像(无需 vision 模型):裁剪、调整 大小、黑白、旋转/翻转、亮度/对比度/模糊以及格式转换。 来源 —— http(s) URL、data: URL、本地路径(绝对路径或相对于 会话 scratch 目录)或通过 temp: { name } 从 scratch 获取的文件。操作 以批处理方式提交到 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)。

输出。 结果被编码为字节并:

如果没有 ops,该工具只返回图片的元数据(宽/高/格式/大小)。

基于 image_tool 的现成文生图方案(免费, 无需 API 密钥)— 第 5.32 节。

示例(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)的单个工具。 Agent 托管 MCP 工具,但本身并不是 MCP 服务器 — mcp_tool 充当客户端,通过 tool: 字段调用服务器上的具体工具。

传输方式:

description 和 parameters(JSON Schema)取自服务器的 tools/list,如果 未在 YAML 中覆盖,因此 LLM 看到的正是服务器所声明的 schema。Schema 在配置加载阶段拉取(而非运行时);如果 加载时服务器不可用 — 则注册 fallback schema,而连接错误 会在调用时返回。

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 MCP 端点 URL(必填)
headers http/sse 额外的请求头
timeout_secs — 请求/握手超时(默认 30)

${ENV_VAR} 在 command、args、env、url 和 headers 中从 进程环境展开 — 密钥不会硬编码进 YAML。

调用模板化。 如果没有 arguments,则向 tools/call 传递来自 LLM 的原始 input。 arguments 字段是 MiniJinja 模板字符串,渲染为 JSON 文档;作用域中可用 input、temp_dir、session_id、user_id、 template。这样 agent 作者可以注入固定字段、将 LLM 输入重映射到服务器 schema,或代入用户标识符:

arguments: '{ "query": "{{ input.query }}", "user": "{{ user_id }}", "limit": 10 }'

到同一服务器的连接会被复用(按 server 池化),因此多个 mcp_tool 引用同一服务器时,会保持一个存活的进程 / HTTP 会话。

5.31 wait_tool

暂停指定的秒数 — 用于给长时间操作(例如基准测试)的轮询 打节奏,而不是连续调用工具几十次。

kind: wait_tool
name: wait
description: "Подождать N секунд."
max_seconds: 120        # потолок на один вызов (по умолчанию 120)

参数:seconds(integer,必填;会被钳制到 1..max_seconds), reason?(string)。响应为 Waited Ns (reason). Continue now. 该工具 是通用的(模块 agent_tools),任何 agent 都可通过 tool_files 使用。

5.32 图片生成(text-to-image)

现成的“文本 → 图片”方案,无需 API 密钥,基于免费服务 Pollinations。这不是单独的 kind,而是由 两个工具组成的组合(script_tool + image_tool 模式)。

更简单的方式是使用原生引擎 image_gen_tool (第 5.33 节)— 它用一个工具完成同样的事情。此方案保留作为 通过 call_tool 组合 script_tool + image_tool 的示例。

两者都位于 config/tools/ 中,可被任何 agent 复用。在 tool_files 中, agent 只需两行即可(路径相对于 agent 目录,因此 ../../tools/):

tool_files:
  - ../../tools/generate_image.yaml   # генерация
  - ../../tools/image_fetch.yaml      # служебная доставка картинки в чат

此后 LLM 会看到 generate_image(prompt, width?, height?, seed?, model?, style?)。

Agent 自己的风格(薄封装)

实现是通用的 config/tools/generate_image.js。要设置默认风格和 尺寸,请在 agent 中创建一个薄封装,引用同一个 脚本,并带有 style / width / height / deliver 字段:

# config/agents/<agent>/tools/generate_image.yaml
kind: script_tool
name: generate_image
description: Нарисовать иллюстрацию в стиле агента.
script: ../../../tools/generate_image.js   # общая реализация
style: "dark historical oil painting, 16th century, muted palette, storm light"
width: 1024
height: 768
parameters:
  type: object
  properties:
    prompt: { type: string }
  required: [prompt]

封装中的 style 会追加到提示词中,并会被调用覆盖(在 参数中的 style);deliver 会更改投递工具的名称(默认 image_fetch)。现成的示例:agent image(无风格)和 egidia (阴郁的历史绘画)。

../../tools/… 链接在配置的文件树中可用(在 git 配置中也可用, 其中有 config/tools/)。Agent 的管理构建器(“Builder”)操作的是 自包含的 agent 包,不会复制其目录之外的文件—— 在积极使用 Builder 时,请将工具副本保留在 <agent>/tools/ 内。

工作原理

脚本对提示词进行编码,组装 URL https://image.pollinations.ai/prompt/<prompt>?width=…&height=…&seed=…&nologo=true 并调用 call_tool("image_fetch", { input: url, ops: [{ "op": "info" }], send: true })。image_fetch 像任何 image_tool 一样,下载 URL,并在 send: true 时返回 file 块;脚本将该块返回到 visual 中,它 会在 UI 中渲染(参见通用字段)。

在没有工具调用服务时(离线 agent-os tool),call_tool 会抛出异常—— 脚本会捕获它,并在 content 中返回现成的 URL(便于在没有服务器的情况下调试 配置)。

限制

5.33 image_gen_tool

原生“文本 → 图片”引擎。与方案 5.32 不同,这是一个单独的 kind:它自己渲染 后端 URL,下载字节并返回 file 块——无需 script_tool、 call_tool 和第二个工具。

kind: image_gen_tool
name: generate_image
description: Сгенерировать картинку по описанию.
url_template: "https://image.pollinations.ai/prompt/{prompt}?width={width}&height={height}&seed={seed}&nologo=true"
model: flux            # добавляется как &model=…, если шаблон без {model}
style: "dark oil painting, 16th century"   # дописывается к промпту
width: 1024
height: 768
max_bytes: 26214400    # лимит размера ответа (по умолчанию 25 МиБ)
# send: true           # отдавать пользователю (по умолчанию true, если нет output)
# output: image.jpg    # имя файла для записи в scratch сессии
# headers: { Authorization: "Bearer ${IMAGE_API_KEY}" }   # ${ENV} раскрывается

调用参数: prompt(必填)、width、height、seed、model、 style、output、send。

YAML 字段 用途
url_template 请求模板;占位符(会进行 URL 编码):{prompt}、{style}、{model}、{width}、{height}、{seed}。为空 → Pollinations
model 默认模型(如果模板中没有 {model},则追加 &model=…)
style 默认风格,通过 , 追加到提示词
width / height 默认尺寸(会被限制在 64..2048)
output / send scratch 文件和投递(与 image_tool 相同)
max_bytes 响应大小限制(默认 25 MiB)
headers 附加请求头;${ENV_VAR} 会从环境展开

工作原理。 引擎从 url_template 组装 URL,下载响应, 检查它是否为可识别的图像(image::guess_format),并 返回 file 块(base64)——图片会在所有渠道中显示 (小组件、Telegram、VK、Yandex Messenger、Android)。后端错误 (例如达到限制时的 HTTP 402)会作为带文本的 success: false 返回。

其他提供商。 只需更改 url_template(如有需要,还可更改 headers):本地 Stable Diffusion/ComfyUI、OpenAI 兼容 API 等。

接入示例:agent image(无风格)和 egidia(阴郁的 历史绘画)。