12 KiB
12 KiB
TOOLKIT WORKFLOW — YAML 驱动的 HTTP 工具链引擎
概述
TOOLKIT WORKFLOW 让你通过编写 YAML 文件来定义 LLM 工具。一个 YAML 文件描述一个工具:它接受哪些参数、调用哪些 HTTP API、如何从响应中提取数据、以及最终返回什么给 LLM。
核心能力:
- 一个 YAML 文件 = 一个完整的 LLM 工具,无需写代码
- 支持多步 HTTP 请求链,步骤之间可以传递变量
- 流程控制:
next跳转步骤、jump降级到备源、abort终止执行 - 键级缓存:
cache缓存变量,同一调用中缺键自动重请求 - 统一提取:
extract字段,语法自描述引擎(路径 / 正则)
YAML 顶层结构
一个工具 YAML 文件包含以下顶层字段:
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
name |
是 | string | 工具名,对应 LLM function.name |
desc |
是 | string | 工具描述,对应 LLM function.description |
params |
否 | array | LLM 可见的参数定义,映射为 function.parameters JSON Schema |
env |
否 | array[string] | 该工具依赖的环境变量名列表,仅作文档和校验 |
steps |
是 | array | 请求步骤链,按顺序执行 |
params — 参数定义
定义 LLM 可以传入的参数,映射为 function calling 的 parameters schema。
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
name |
是 | string | 参数名,在模板中通过 ${param:key} 引用 |
type |
是 | string | 取值:string / number / integer / boolean |
required |
是 | boolean | 是否必填 |
description |
是 | string | 参数说明,LLM 据此理解参数含义 |
default |
否 | any | 默认值,LLM 未传时自动使用 |
steps — 请求步骤
每个步骤定义一个 HTTP 请求及其后续处理。
步骤字段
| 字段 | 必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
url |
是 | string | — | 请求 URL,支持模板语法 |
method |
否 | string | GET |
HTTP 方法:GET / POST / PUT / DELETE / PATCH |
headers |
否 | map | — | 请求头键值对,值支持模板语法 |
query |
否 | array | — | URL 查询参数,格式为 [{key, value}] 元组列表,值支持模板语法 |
body |
否 | string | — | 请求体,支持模板语法 |
timeout |
否 | integer | 30 | 超时时间(秒) |
cache |
否 | boolean | false | 是否对该步骤启用键级缓存 |
next |
否 | integer | — | 步骤成功后跳转到第几个步骤(0-based),不设则顺序执行下一步 |
var |
否 | array | — | 变量提取列表 |
result |
否 | string | — | 最终返回模板,有此字段则该步为终步 |
步骤示例
steps:
- url: ${env:BASE_URL}/auth/token
method: POST
headers:
Content-Type: application/json
body: |
{"client_id": "${env:CLIENT_ID}", "client_secret": "${env:CLIENT_SECRET}"}
timeout: 15
cache: true
var:
- name: token
extract: access_token
abort: true
next: 1
- url: ${env:BASE_URL}/orders/${param:order_id}
method: GET
headers:
Authorization: Bearer ${step0:token}
var:
- name: status
extract: data.status
- name: amount
extract: data.amount
result: |
订单号: ${param:order_id}
状态: ${step1:status}
金额: ${step1:amount}
var — 变量提取
每个步骤执行完 HTTP 请求后,按顺序处理 var 列表中的条目,从响应中提取命名变量。提取的变量通过 ${stepN:var_name} 在后续步骤中引用。
extract — 提取表达式
一个字段覆盖所有提取场景。值的语法决定使用的引擎:
| 语法 | 引擎 | 说明 |
|---|---|---|
不以 / 开头 |
路径引擎 | 对 JSON/YAML 响应执行结构化路径导航 |
以 / 开头且以 / 结尾 |
正则引擎 | 对原始响应文本执行正则匹配,取捕获组 1 |
路径引擎:自动检测响应格式(先 JSON,失败则 YAML),然后按路径导航取值。
| 语法 | 含义 | 示例 |
|---|---|---|
key |
访问对象字段 | data.status |
key[N] |
访问数组第 N 个元素 | items[0].name |
key[] |
遍历数组所有元素 | books[] |
key[].field |
遍历数组,对每个元素取字段 | books[].title |
键名建议仅使用
[a-zA-Z0-9_],避免含.[]的特殊键名。
正则引擎:/pattern/ 形式,对原始响应文本执行正则匹配,取第一个捕获组。
# 路径:从 JSON 响应中提取
var:
- name: token
extract: auth.access_token
# 正则:从任意文本中提取
var:
- name: session
extract: /session[= ]([a-f0-9]+)/
提取失败处理(每个条目最多选一种)
| 配置 | 提取成功 | 提取失败 |
|---|---|---|
| 不设任何失败处理 | 存入变量 | 存入空字符串 "",继续执行 |
default: "值" |
存入变量 | 存入默认值,继续执行 |
abort: true |
存入变量 | 终止整个工具,返回错误给 LLM |
jump: N |
存入变量 | 跳转到第 N 个步骤执行,N 从 0 开始 |
var 条目完整字段
| 字段 | 必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
name |
是 | string | — | 变量名,通过 ${stepN:name} 引用 |
extract |
否 | string | — | 提取表达式,语法自描述引擎(路径 / 正则) |
default |
否 | string | — | 提取失败时的默认值 |
abort |
否 | boolean | false | 提取失败时是否终止工具 |
jump |
否 | integer | — | 提取失败时跳转到第几个步骤(0-based) |
流程控制
三种流程控制机制,覆盖顺序执行、条件跳转和异常终止。
next — 成功后跳转
- 位置:步骤级别
- 触发条件:步骤所有 var 都没有因 abort/jump 而失败
- 效果:跳转到指定步骤号(0-based),不设则顺序执行下一步
- 用途:跳过某些步骤、实现条件分支
jump — 提取失败时降级
- 位置:var 条目级别
- 触发条件:该条目的提取失败且未设置 default
- 效果:跳转到指定步骤号(0-based),当前步骤剩余 var 不再执行
- 用途:主数据源失败时自动切换到备数据源
abort — 提取失败时终止
- 位置:var 条目级别
- 触发条件:该条目的提取失败
- 效果:终止整个工具执行,返回错误信息给 LLM
- 用途:关键变量(如认证 token)获取失败时立即报错
cache — 键级缓存
当步骤设置 cache: true 时,该步骤提取的所有变量会被缓存。
缓存行为:
- 命中:缓存中存在该步骤所有 var.name → 跳过 HTTP 请求,直接返回缓存值
- 未命中:任意一个 var.name 缺失 → 发起 HTTP 请求,提取所有变量,全部存入缓存
- 生命周期:单次工具调用期间(内存级),工具返回后释放
- 缓存键:由步骤的
url + method + headers + body模板展开后的哈希确定
典型用法:第一步获取认证 token 并缓存,后续多步复用 token 时不会重复请求认证接口。
模板语法
以下字段支持模板语法:url、headers 的值、body、result。
三种引用
| 语法 | 来源 | 示例 |
|---|---|---|
${param:key} |
LLM 传入的工具参数 | ${param:city}、${param:order_id} |
${env:VAR} |
系统环境变量 | ${env:API_KEY}、${env:BASE_URL} |
${stepN:var_name} |
第 N 个步骤提取的变量,N 从 0 开始 | ${step0:token}、${step1:status} |
约束
- 禁止嵌套引用:
${step0:${env:KEY}}不允许 - 禁止原始步骤引用:
${step:0}不允许,必须先通过 var 提取为命名变量
result — 最终返回
步骤的 result 字段定义该工具最终返回给 LLM 的内容。
- 如果某步设置了
result,该步即为终步,执行后不再继续后续步骤 - 如果所有步骤都未设置
result,默认返回最后一步的原始响应体 result支持模板语法,可以拼接多个变量和文字
# 返回单个变量
result: ${step1:status}
# 多行模板拼接
result: |
订单号: ${param:order_id}
状态: ${step1:status}
金额: ${step1:amount}
执行流程
1. 加载 YAML → 解析为 YamlToolDef
2. 解析 LLM 参数 → params HashMap
3. 加载 env 声明的环境变量 → env HashMap
4. 初始化 cache = {}
5. step_idx = 0
while step_idx < steps.len():
┌─ 当前步骤执行 ──────────────────────────────┐
│ │
│ [cache: true?] │
│ ├─ 缓存命中(所有 var 键都存在)→ 跳过HTTP │
│ └─ 缓存未命中 → 继续 │
│ │
│ 展开 url/headers/body 中的模板 │
│ ${param:key} → params["key"] │
│ ${env:VAR} → env["VAR"] │
│ ${stepN:var} → ctx.vars[(N, var)] │
│ │
│ HttpRequest 执行 → HttpResponse │
│ 保存到 ctx.steps[step_num] │
│ │
│ for each var: │
│ extract 语法分发: │
│ ├─ /.../ → 正则引擎,取捕获组1 │
│ └─ 其他 → 路径引擎(JSON→YAML 自动检测) │
│ ├─ 成功 → 存入 ctx.vars + step_vars │
│ └─ 失败 → │
│ ├─ abort:true → 终止,返回错误 │
│ ├─ default:x → 使用默认值 │
│ ├─ jump:N → step_idx = N, break │
│ └─ (无) → 空字符串 │
│ │
│ [cache: true?] → 将 step_vars 存入 cache │
│ │
│ [result 存在?] │
│ └─ 展开 result 模板 → 返回给 LLM → 结束 │
│ │
│ [next 存在?] │
│ ├─ next:N → step_idx = N │
│ └─ (无) → step_idx += 1 │
│ │
└──────────────────────────────────────────────┘
6. 循环结束 → 返回最后一步原始响应体
错误处理
| 场景 | 处理方式 |
|---|---|
| YAML 文件格式错误 | 启动时打印警告,跳过该文件 |
| 模板引用了未定义的参数 | 替换为空字符串,记录警告日志 |
| 环境变量未设置 | 替换为空字符串,记录警告日志 |
| HTTP 请求失败(连接/超时) | 返回错误详情给 LLM |
var.abort: true 且提取失败 |
终止,返回 "变量 xxx 提取失败" |
var.jump: N 且提取失败 |
跳转到第 N 个步骤,N 从 0 开始,不报错 |
var.default 且提取失败 |
使用默认值,不报错 |
| 路径语法错误(空段、非法索引) | 返回错误给 LLM,附带路径表达式 |
| 路径键不存在 / 索引越界 | 提取失败,触发 default/abort/jump |
| 正则语法错误 | 返回错误给 LLM,附带正则表达式 |
| 正则无匹配 | 提取失败,触发 default/abort/jump |
| 响应体非 JSON 也非 YAML(路径引擎) | 返回错误给 LLM |
next / jump 目标步骤不存在 |
终止,返回配置错误 |
扩展预留
以下字段预留供后续版本实现:
| 字段 | 位置 | 用途 |
|---|---|---|
retry |
steps[] |
失败重试次数与退避策略 |
cache.ttl |
steps[] |
缓存有效期(秒) |
validate |
params[] |
参数级正则校验 |
sensitive |
env[] |
标记敏感环境变量,日志脱敏 |
loop |
steps[] |
条件循环(分页自动翻页) |
export |
steps[] |
将变量导出为环境变量供子进程使用 |
pre_request |
顶层 | 工具级别的前置请求(全局认证) |