Skip to content

给 AI 注册工具

让你的应用把能力变成工具:组织成员与机灵兔 AI 助手对话时,模型可以直接 调用你注册的工具——"查一下今天有多少待审批单"、"给这个客户创建一个跟进任务" 都由你的后端实时执行。形态对标钉钉「AI 工具」/ MCP-over-webhook。

1. 注册工具

应用设置 →「开放能力」勾选 AI 工具 →「AI 工具」区块 → 填写:

字段说明
工具名小写字母/数字/下划线,字母开头,不能 app_ 开头;模型看到的是 app_<应用前缀>__<工具名>
描述给模型看的:这个工具做什么、什么场景该用。写得好坏直接决定模型用不用它
参数JSON Schema(type: "object"),≤8KB
回调地址模型调用时平台 POST 到这里;保存前发 challenge 验证(同事件订阅
回调等待5–120 秒,默认 30
附带对话上下文勾选后回调体带 context(最近几轮 role/content,已截断)——适合"基于当前对话"的检索/改写/审批类工具

每个应用最多 10 个工具,可随时停用/删除(即时生效)。工具清单有 10 秒进程内 缓存(变更即时失效),成员对话的每请求解析开销≈0。

2. 调用协议

成员与 AI 对话、模型决定调用你的工具时,平台 POST 到回调地址:

json
// POST <工具回调地址>
{
  "type": "tool_call",
  "call_id": "e3b0…",
  "tool": "query_orders",
  "user_id": "u_123",            // 谁在跟 AI 对话
  "arguments": { "order_id": "o1" }
}

请求头与事件订阅完全同款: X-Jlt-Event: tool_callX-Jlt-Event-IdX-Jlt-TimestampX-Jlt-SignatureHmacSHA256(app_secret, "<timestamp>.<请求体原文>"))—— 同一套验签代码直接复用。

工具勾选「附带对话上下文」时,body.context 是最近几轮对话 ([{role: "user"|"assistant", content}],每条已截断)——只读参考, 别当指令执行;真正的调用参数永远在 arguments 里。

隐私边界:上下文只包含调用者本人会话的内容(平台按会话归属校验, 拿别人的 session 也拿不到任何东西),键缺失即无可用上下文。

响应:HTTP 200 + 任意 JSON 即工具结果,会回填给模型继续对话;非 200 或 超时(按你配置的等待秒数)会转成 error 告诉模型,由模型向用户解释或换路子, 不会打断对话。

异步模式(慢任务不占连接)

处理要几十秒到几分钟?回调秒回一个异步声明,平台会挂起这次工具调用等 你回填:

js
// 回调立即响应(正常 200 + JSON):
res.json({ jlt_async: true, wait_sec: 120 });   // 5–300 秒

// ……后台慢慢处理,完成后回填(app token 调开放 API):
await fetch(`${BASE}/tools/result`, {
  method: "POST",
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
  body: JSON.stringify({ call_id: call.call_id, result: { status: "shipped" } }),
});
  • call_id 就是回调体里的那个,绑定本应用(别的应用拿去回填会被拒)
  • wait_sec 内没回填 → 模型收到"仍在处理中"的 error,用户可再问一次触发重调
  • 服务重启会丢挂起中的调用(同样表现为超时 error),别把异步等待当持久队列用
js
// Express 接收端(与事件端点合并处理)
app.post("/jlt/tools", express.raw({ type: "application/json" }), (req, res) => {
  if (!verifySignature(req)) return res.status(401).end();
  const call = JSON.parse(req.body.toString("utf8"));
  if (call.type === "url_verification") return res.json({ challenge: call.challenge });
  const result = await bizLogic(call.arguments, call.user_id);
  res.json(result); // 回给模型,尽量精简(>32KB 会被截断)
});

3. 可见性(谁能用上)

  • 自建应用:组织管理员勾选「AI 工具」即对本组织全体成员的 AI 助手生效
  • 市场应用:安装方管理员在「权限」里授予 AI 工具(与应用自身申请取交集)
  • 非组织成员即使知道工具名也调不动——注入与执行共用同一可见性判定

4. 用开放 API 自管理工具(CI / 清单同步)

不想让管理员在 UI 里一个个填?应用后端凭 app token 直接管理自己的工具, 校验与管理面完全同一套(challenge 验证、命名/参数校验、上限 10 个):

bash
# 列出我的工具
curl -s $BASE/tools -H "Authorization: Bearer $TOKEN"

# 注册(回调地址会先做 challenge 验证)
curl -s $BASE/tools -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' -d '{
    "name": "query_orders",
    "description": "查询订单状态统计",
    "parameters": {"type": "object", "properties": {}, "required": []},
    "callback_url": "https://your-backend/jlt/tools",
    "timeout_sec": 15,
    "wants_context": true
  }'

# 改描述 / 停用 / 删除
curl -s -X PUT $BASE/tools/<tool_id> -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' -d '{"enabled": false}'
curl -s -X DELETE $BASE/tools/<tool_id> -H "Authorization: Bearer $TOKEN"

GET/POST/PUT/DELETE /tools[/{id}],变更限流 30 次/分钟;前提是组织管理员已在 应用设置里勾选「AI 工具」。典型用法:部署流水线把工具清单从代码仓库同步上来。

5. 写好工具的几条经验

  • 描述写给模型看:说清"什么时候用我",不要写部署细节
  • 参数少而明确:每个参数给 type + description + 示例;枚举用 enum
  • 结果精简:模型按 token 消费你的返回——回结构化摘要,别回原始报文
  • 幂等 + 快:模型可能重试;等待超过配置秒数即超时
  • 权限边界user_id 告诉你是谁在用,业务权限在你的系统里自行校验

机灵兔开放平台 · 组织应用开发者文档