Skip to content

在插件中添加工具

Tool 会加入 Agent 可见工具集,最终名称由插件 id 和 Tool name 共同限定。参数必须使用 Zod 4 对象 Schema;普通对象、JSON Schema、字符串或只模拟 toJSONSchema 的对象都会在插件激活时被拒绝。

字段类型必填说明
namestringTool 名称,不能为空
descriptionstring给模型读取的功能说明,不能为空
parametersZod object schema直接注册时使用;必须同时支持 safeParse 和 toJSONSchema,且生成 object JSON Schema
agentIdsreadonly string[]仅向指定 Agent 暴露
serialExecutionboolean为 true 时要求串行执行,默认为 false
getDeclaredPermissionsfunction根据参数声明本次调用需要的权限
executeasync function执行 Tool
stopfunction宿主要求停止 Tool 时调用
renderobjectCLI 和 GUI 自定义渲染器

使用 SDK 的 tool 辅助函数时传入 args,而不是 parameterstool 会执行 parameters: z.object(args) 的转换。直接调用 ctx.tools.register 时始终传 parameters,不能传 args

execute(args, context, result) 接收:

参数字段说明
argsSchema 解析结果已通过 parameters 校验的工具参数
contexttaskId当前任务 id,某些无任务场景可能为空
contextworkspace当前工作空间,可能为空
contextabortAbortSignal,用于响应任务停止
resultattachResult(chunk)追加过程输出
resultupdateResult(text)替换文本结果
resultupdateResultObject(object)更新结构化结果

execute 可以返回 undefinedstring,或形如 output + resultObject 的对象。返回 string 会成为最终文本;对象中的 output 是最终文本,resultObject 是可选结构化结果。

getDeclaredPermissions 返回 PermissionRequest 数组。每一项包含:

字段可选值说明
resourceTypefile、network、skill、plugin、*受保护资源类型
actionread、write、execute、access、*操作
resourcePathstring实际路径、URL、Skill 名或插件 id,不要用笼统占位值

render.gui 接收 ToolRenderContext,返回 textcodekeyValue 内容;render.cli 额外接收 width,返回 string[]。渲染失败只会回退到默认显示,不会改变 Tool 执行结果。

ToolRenderContext 字段:

字段类型说明
toolstring完整 Tool 名
callIdstring本次调用 id
statuspending、running、success、error调用状态
argsunknown调用参数
resultstring可选文本结果
resultObjectobject可选结构化结果
widthnumber仅 CLI 渲染器可用的终端宽度

GUI 返回值:

{ type: 'text', text: 'plain text' }
{ type: 'code', code: '{"ok":true}', language: 'json' }
{ type: 'keyValue', items: [{ label: 'Status', value: 'Ready' }] }
import { definePlugin, tool } from '@bitclub.ai/opendesk-plugin-sdk';
export default definePlugin({
id: 'greeting-tools',
capabilities: ['tool'],
setup(ctx) {
return ctx.tools.register(tool({
name: 'greet',
description: 'Generate a greeting for one person',
args: {
name: tool.schema.string().min(1).describe('Person to greet')
},
getDeclaredPermissions(args, context) {
return [];
},
async execute(args, context, result) {
result.attachResult('Preparing greeting');
if (context.abort.aborted) {
return { output: 'Cancelled' };
}
return {
output: 'Hello, ' + args.name + '!',
resultObject: { greeted: args.name }
};
},
render: {
gui({ status, resultObject }) {
return {
type: 'keyValue',
items: [
{ label: 'Status', value: status },
{ label: 'Name', value: String(resultObject?.greeted || '') }
]
};
},
cli({ status, result, width }) {
return ['[' + status + '] ' + (result || '') + ' (width=' + width + ')'];
}
}
}));
}
});

无 SDK Tool 仍需 Zod 4:

{
"name": "greeting-tools",
"version": "0.1.0",
"type": "module",
"dependencies": {
"zod": "^4.2.1"
}
}
import { z } from 'zod';
export default {
id: 'greeting-tools',
capabilities: ['tool'],
setup(ctx) {
return ctx.tools.register({
name: 'greet',
description: 'Generate a greeting for one person',
parameters: z.object({
name: z.string().min(1).describe('Person to greet')
}),
getDeclaredPermissions(args, context) {
return [];
},
async execute(args, context, result) {
result.attachResult('Preparing greeting');
if (context.abort.aborted) {
return { output: 'Cancelled' };
}
return {
output: 'Hello, ' + args.name + '!',
resultObject: { greeted: args.name }
};
},
render: {
gui({ status, resultObject }) {
return {
type: 'keyValue',
items: [
{ label: 'Status', value: status },
{ label: 'Name', value: String(resultObject?.greeted || '') }
]
};
},
cli({ status, result, width }) {
return ['[' + status + '] ' + (result || '') + ' (width=' + width + ')'];
}
}
});
}
};