工具 — 计算与操作
🔵 执行具体操作的引擎:脚本、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" } } ] }
格式与限制
create支持docx(来自 Markdown)、xlsx(来自字符串/CSV)和pptx(来自slides: [{ title, bullets[] }])。convert提供html、svg和pdf。对于pdf,引擎使用 导出器插件(officecli_pdf_exporter)——一个独立的二进制文件,OfficeCLI 通过OFFICECLI_PLUGIN_EXPORTER_PDF找到它。该插件使用 OfficeCLI 引擎将文档渲染为 HTML, 然后通过无头 Chromium 浏览器打印为 PDF。如果没有浏览器,它会自动下载 (chrome-headless-shell,来自 Chrome for Testing)到~/.cache/agent-os/browser(Linux)/%LOCALAPPDATA%\agent-os\browser(Windows)。可在 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 以文本形式返回内容(如果是 ≤ 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(以 ресурс.действие 表示法)
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(内联或 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)
一次性步骤,通过工具本身执行:
- 调用
authorize操作——将返回同意 URL。 - 打开 URL,登录 Google 并授权访问。
- 复制代码并调用
authorize_code,传入code字段——refresh 令牌 将保存到token_file。
{ "action": "authorize" }
{ "action": "authorize_code", "code": "4/0A..." }
之后工具会自动通过 refresh 令牌刷新 access 令牌。
每个服务都支持 通用网关 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": "*" } }
] }
这是针对便捷操作未覆盖的任何操作的逃生通道(method: documents.batchUpdate + body: {requests: [...]}
也能达到同样效果)。
API 限制
- Docs API 不支持 分栏(multi-column layout)——这 只是 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": [ ... ] }
通用网关(用于非标准方法):
{ "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 —— 解析后的响应。
配置访问权限
- 在 Cloud Console 中启用所需的 API(Drive / Sheets / Docs / Slides)。
- 对于 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": "/" } }
配置访问权限
- 在 oauth.yandex.ru 注册应用 (需要 client_secret 时选「Web 服务」类型,或选「用于 API 访问」)。
- 指定所需权限:对于磁盘 ——
cloud_api:disk.read/write/info, 对于日历 ——calendar:all。 redirect_uri(oauth.redirect_uri)必须与应用的回调 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 |
来自 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-pollgetUpdates。如果操作员之前给 机器人写过消息 —— 卡片会发到同一个聊天中。
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)。
输出。 结果被编码为字节并:
- 如果设置了
output,则写入会话的 scratch 目录(之后可通过temp: { name }、file_tool等访问); - 如果
send: true为图片,则作为file块(base64)返回给用户 — 在所有地方以内嵌预览显示:Web 组件(<img>)、Telegram、VK 和 Yandex Messenger (照片,用于image/jpeg|png|gif|webp;其余格式作为文档发送), Android(内联预览 + “打开”/“保存”)。可以两者同时进行, 也可以只做其中之一。
如果没有 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: 字段调用服务器上的具体工具。
传输方式:
stdio— 本地进程(command+args+env),换行分隔的 JSON-RPC;http/sse— Streamable HTTP(POST JSON-RPC,响应为application/json或text/event-stream;sse—http的别名)。
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的示例。
generate_image(script_tool)— 根据提示词构建图片 URL,并通过call_tool将其传给辅助工具;image_fetch(image_tool)— 按 URL 下载图片并返回file块;脚本将其透传到自己的visual,因此图片 在所有渠道中显示(小组件、Telegram、VK、Yandex Messenger、Android)。
两者都位于 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(便于在没有服务器的情况下调试 配置)。
限制
- 服务是公开且免费的:可能存在请求限制和周期性
延迟。模型列表(
model,例如flux、turbo)会变化;默认 使用flux。 - 免费套餐会添加水印
pollinations.ai;nologo=true并不总能有所帮助。 - 对于私有/商业生成,方案会切换到本地 Stable Diffusion/ComfyUI 或其他 API——只需更改脚本中 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(阴郁的
历史绘画)。