news 2026/9/12 15:57:06

Composio SDK 工具修饰器(Modifiers)实战:用 modifySchema / beforeExecute / afterExecute 精确掌控 Agent 工具

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Composio SDK 工具修饰器(Modifiers)实战:用 modifySchema / beforeExecute / afterExecute 精确掌控 Agent 工具

Composio SDK 工具修饰器(Modifiers)实战:用 modifySchema / beforeExecute / afterExecute 精确掌控 Agent 工具

【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio

工具修饰器(Modifiers)是 Composio SDK 提供给开发者的一组生命周期钩子,让你能够在工具被 LLM 使用之前、执行之中与执行之后分别改写其Schema(定义)入参(params)执行结果(result)。本文以仓库中的 ts/examples/modifiers 示例为骨架,结合 modifiers.types.ts 的类型定义与 Tools.ts 的底层实现,完整讲解如何通过这三种修饰器对 HackerNews 等工具进行细粒度定制,读完即可在非 Agentic 与 Agentic(Vercel AI SDK)两种模式下落地使用。

一、示例定位:Composio 工具修饰器的最小可运行演示

ts/examples/modifiers/README.md 将本示例定位为“Composio SDK + Vercel AI SDK”的集成演示,核心诉求是让 AI 应用能够调用 HackerNews 数据。不过,与仓库中其他示例不同,该目录真正落地的 src/index.ts 是一份修饰器(modifiers)专题演示:它没有实现流式聊天界面,而是聚焦展示modifySchemabeforeExecuteafterExecute三个钩子在“非 Agentic”与“Agentic”两种 Provider 模式下的用法,并以console.log(tools)输出最终装配好的工具对象供开发者直接观察。

目录结构非常精简:

ts/examples/modifiers/ ├── README.md # 示例说明(本文所述关联文档) ├── package.json # 依赖与运行脚本 ├── tsconfig.json # TypeScript 配置 └── src/index.ts # 修饰器演示源码

从 package.json 可以看到,示例依赖@composio/core(核心 SDK)与@composio/vercel(Vercel 集成),并通过catalog:引用 workspace 中的ai@ai-sdk/openai;运行脚本为bun src/index.ts(Bun 运行时),类型检查脚本为tsc --noEmit -p ./tsconfig.json

二、环境准备与快速运行

按照 README 的 Getting Started 章节,需要准备:

前置条件说明
Node.js建议使用最新 LTS 版本
pnpmv10.8.0 及以上;若使用bun src/index.ts则需 Bun 运行时
Composio API Key用于初始化Composio客户端
OpenAI API KeyAgentic 模式下供 Vercel AI SDK 调用 GPT-4 等模型

启动步骤(在当前仓库根目录下执行):

# 1. 进入示例目录 cd ts/examples/modifiers # 2. 安装依赖 pnpm install # 3. 复制环境变量模板 cp .env.example .env

注意:当前仓库中该示例目录没有随附.env.example文件,README 中的.env配置项(COMPOSIO_API_KEYOPENAI_API_KEY)需要你自行创建:

COMPOSIO_API_KEY=your_composio_api_key OPENAI_API_KEY=your_openai_api_key

随后即可运行:

bun src/index.ts # 或 pnpm start pnpm typecheck # 仅做类型检查,不输出产物

三、两种 Provider 模式:非 Agentic 与 Agentic 的修饰器差异

src/index.ts 的核心价值在于用同一把工具HACKERNEWS_GET_USER对比展示了两种获取工具的方式:

1. 非 Agentic 模式—— 直接使用Composio客户端,只能传入modifySchema

const composio = new Composio({ apiKey: process.env.COMPOSIO_API_KEY, }); const tools = await composio.tools.get('default', 'HACKERNEWS_GET_USER', { modifySchema: ({ toolSlug, toolkitSlug, schema }) => { if (toolSlug === 'HACKERNEWS_GET_USER') { schema = { ...schema, inputParameters: { type: 'object', properties: { ...schema.inputParameters?.properties, userId: { type: 'string', description: 'The user ID to get the user for', }, }, }, }; } return schema; }, }); console.log(tools);

2. Agentic 模式—— 传入provider: new VercelProvider()后,三种修饰器全部可用:

const vercel = new Composio({ apiKey: process.env.COMPOSIO_API_KEY, provider: new VercelProvider(), // 将工具包装为 Vercel AI SDK 的 Tool }); const agenticTools = await vercel.tools.get( 'default', { tools: ['HACKERNEWS_GET_USER'] }, { afterExecute: ({ toolSlug, toolkitSlug, result }) => { // 修改执行结果 return result; }, beforeExecute: ({ toolSlug, toolkitSlug, params }) => { // 修改执行参数 return params; }, modifySchema: ({ toolSlug, toolkitSlug, schema }) => { // 修改工具 schema return schema; }, } ); console.log(agenticTools);

注意两处关键差异(源码中注释亦明确标注):

  • 获取方式:非 Agentic 模式第二个参数直接传工具 slug 字符串;Agentic 模式则传{ tools: ['HACKERNEWS_GET_USER'] }对象;
  • 能力边界:非 Agentic 模式(ToolOptions)只支持modifySchema(以及beforeFileUpload);Agentic 模式(AgenticToolOptions)额外支持beforeExecuteafterExecute

这种差异并非人为约定,而是由类型系统强制保证的,详见下文第五节。

四、modifySchema:在工具暴露给 LLM 之前改写其定义

modifySchemaTransformToolSchemaModifier类型的回调,签名定义于 modifiers.types.ts:

export type TransformToolSchemaModifier = (context: { toolSlug: string; toolkitSlug: string; schema: Tool; }) => Tool | Promise<Tool>;

它的用途包括:自定义输入/输出参数的描述、增删改参数以满足业务需求、改写工具名称与描述使其更贴合应用上下文、实现 Schema 的版本化或特性开关等。类型注释中给出了比示例更完整的改造样例,例如为HACKERNEWS_GET_USER补充带校验约束的userId参数、includeSubmissions布尔开关与submissionLimit数值范围:

const modifySchema = ({ schema, toolSlug, toolkitSlug }) => { if (toolSlug === 'HACKERNEWS_GET_USER') { return { ...schema, name: 'Get HackerNews User Profile', description: 'Retrieve detailed user information from HackerNews', inputParameters: { ...schema.inputParameters, userId: { type: 'string', description: 'The HackerNews username to retrieve information for', required: true, minLength: 2, maxLength: 15, pattern: '^[a-zA-Z0-9_-]+$' }, submissionLimit: { type: 'number', description: 'Maximum number of submissions to return', default: 10, minimum: 1, maximum: 100 } } }; } return schema; };

底层实现:在 Tools.ts 中,getgetRawComposioToolBySluggetRawComposioTools等方法都会在拿到后端返回的原始工具后调用applySchemaModifiers将用户提供的modifySchema逐工具应用(参见 Tools.ts 与 Tools.ts)。测试 modifiers.test.ts 验证了两点:单个工具获取时修饰器恰好被调用一次,且回调收到的上下文包含toolSlugtoolkitSlugschema;批量获取多个工具(TOOL1TOOL2)时修饰器会被逐个调用并分别改写name字段。

五、beforeExecute / afterExecute:拦截执行前后的请求与响应

5.1 签名与参数

两个执行期修饰器定义于 modifiers.types.ts:

export type beforeExecuteModifier = (context: { toolSlug: string; toolkitSlug: string; params: ToolExecuteParams; }) => Promise<ToolExecuteParams> | ToolExecuteParams; export type afterExecuteModifier = (context: { toolSlug: string; toolkitSlug: string; result: ToolExecuteResponse; }) => Promise<ToolExecuteResponse> | ToolExecuteResponse;
  • beforeExecute:在工具真正执行前拿到即将发送的参数params,典型场景包括注入认证参数/请求头、转换输入数据格式、追加上下文信息、做请求校验与归一化。类型注释给出了为所有请求追加X-API-KeyX-Request-ID等头部的完整示例。
  • afterExecute:在工具执行完成后拿到响应result(含dataerrorsuccessfullogId等字段),典型场景包括把响应转换为更便于下游消费的结构、统一错误处理与日志/埋点、为成功响应补充派生数据。

5.2 底层调用链(以 Session 执行为例)

在 Tools.ts 中可以看到beforeExecute的插入位置:它在文件上传预处理(applyFileUploadModifiers)之后才被调用,因此回调中看到的params与真正发送到 Tool Router 的参数完全一致;修改后的参数会写入executePayload.arguments发出。执行完成后,Tools.ts 再调用afterExecute,将修饰器返回的结果作为最终ToolExecuteResponse返回给调用方。两条钩子均支持返回 Promise,也支持抛错中断流程(非函数类型的修饰器会触发ComposioInvalidModifierError,见 Tools.ts 与 Tools.ts)。

5.3 测试佐证

modifiers.test.ts 的 Execution Modifiers 用例验证了完整行为:

  • beforeExecute把参数{ limit: 5 }改写为{ limit: 10 }后,mockClient.tools.execute收到的实际参数即为改写后的值(L72-L104);
  • afterExecute在响应data上追加{ enhanced: true },最终result.data确认包含该字段(L106-L131);
  • Combined Modifiers 用例(L134-L296)同时注入三种修饰器,验证modifySchema改写描述与标签、beforeExecute触发埋点并注入tracking参数、afterExecute在成功结果上追加processed字段且不触发错误日志。

六、类型体系:修饰器如何随 Provider 自动区分能力

修饰器能力的差异由 modifiers.types.ts 中的类型组合精确建模:

类型包含的钩子适用场景
ToolOptions(L377-L383)modifySchemabeforeFileUpload非 Agentic Provider
ExecuteToolModifiers(L412-L424)beforeExecuteafterExecutebeforeFileUpload单次工具执行
AgenticToolOptions(L587)ToolOptions & ExecuteToolModifiersAgentic Provider(OpenAI、Vercel 等)
SessionExecuteMetaModifiers(L537-L549)会话版beforeExecute/afterExecuteTool Router 会话执行
SessionMetaToolOptions(L628)ToolOptions & SessionExecuteMetaModifiers会话工具获取

其中的ProviderOptions<TProvider>(L658-L663)利用条件类型:当 Provider 是BaseAgenticProvider的子类(如VercelProvider)时自动解析为AgenticToolOptions,否则解析为ToolOptions。这正是示例源码中“非 Agentic 只能传modifySchema,Agentic 可以传三个钩子”这一行为在编译期的保证——写错配置会直接得到类型错误(示例源码注释中也留下了// what is the type error i am getting here?这类排查提示)。

七、进阶能力:会话上下文修饰器与文件上传钩子

除示例展示的三个钩子外,同一类型文件中还定义了面向更复杂场景的修饰器:

1. 会话上下文修饰器beforeExecuteMetaModifier/afterExecuteMetaModifier(L459-L498)专用于 Tool Router 会话执行,回调额外携带sessionId,且params类型为MetaToolArguments(非空的工具参数,见 L431)。helper 工具使用composiotoolkit slug,预加载的应用工具使用各自 toolkit slug。典型用法是为会话内工具注入sessionMetadata、统计startTime或在结果上附加sessionInfo

2. 文件上传钩子beforeFileUploadModifier(L204-L209)在 SDK 读取并上传file_uploadable值之前触发,context.source区分三种输入——'path'(本地文件系统路径)、'url'http(s)://链接)、'file'File对象,此时path仅为文件名)。返回字符串可替换上传输入(重写路径、重定向 URL、把File换成本地路径上传);返回false或抛错则中止上传并抛出ComposioFileUploadAbortedError

八、Agentic 模式内部机制:VercelProvider 如何包装工具

在 Agentic 模式下,provider: new VercelProvider()负责把 Composio 工具翻译成 Vercel AI SDK 的tool()格式,其核心逻辑在 ts/packages/providers/vercel/src/index.ts 的wrapTool方法(L113-L169)中:

  1. Schema 规范化:先通过deduplicateJsonSchemaRequiredArrays去重required数组;若构造时开启strict: true,再用toStrictJsonSchema将 JSON Schema 重写为结构化输出所需的严格形态——所有属性必填(可选参数变为可空),无法表达的构造会保留原 Schema 并输出警告日志;
  2. Zod 转换jsonSchemaToZodSchema(dereferenceJsonSchema(...))把展开$ref后的 Schema 转为 Vercel AI SDK 所需的 Zod Schema(Zod 转换器不跟随$ref,因此需预先内联定义);
  3. 执行桥接execute回调里先用normalizeToolArguments处理模型偶尔把工具入参输出成 JSON 字符串的情况,再调用composio.tools.execute;strict 模式下还会用omitNullToolArguments剔除“值为 null 表示省略”的可选参数。

wrapTools(L234-L239)则把多个工具按 slug 组装成ToolSet字典返回。也就是说,示例中vercel.tools.get(...)返回的agenticTools,本质上就是可以直接喂给 Vercel AI SDK 的tools参数。

九、最佳实践与注意事项

综合示例、类型注释与源码实现,总结以下实践要点:

  1. 按 Provider 类型选择钩子:非 Agentic 场景(如直接用 SDK 调用工具)只有modifySchema;需要beforeExecute/afterExecute时使用VercelProvider等 Agentic Provider,编译期类型会给出正确约束。
  2. modifySchema是纯定义变换:它发生在工具暴露给消费者之前,不影响后端工具本身,适合做参数裁剪、描述增强、命名定制;注意保持返回对象为合法 JSON Schema(inputParameters需为type: 'object'结构)。
  3. beforeExecute看到的是最终参数:文件上传预处理先于它执行(Tools.ts),因此不要在前置钩子里重复处理文件上传逻辑。
  4. afterExecute的返回值即最终结果:无论成功失败都会进入该钩子,可统一在此处做日志埋点与错误增强;修改data时建议基于result.data展开合并,避免丢失successfullogId等字段。
  5. 异步与错误处理:三个修饰器都支持返回PromisebeforeExecute抛错会中止执行,afterExecute抛错则中断结果返回,可据此实现校验失败、鉴权刷新等分支逻辑。
  6. 示例为最小演示:README 中描述的 HackerNews 头条摘要(GPT-4 + 流式响应)属于该示例的设计目标;实际 src/index.ts 以console.log输出装配后的工具对象为主,用于快速验证修饰器链路,落地完整 Agent 应用时可在其基础上接入ai@ai-sdk/openai构建流式对话接口。

十、延伸阅读

  • 示例入口与运行脚本:ts/examples/modifiers/src/index.ts、ts/examples/modifiers/package.json
  • 修饰器全部类型定义与示例代码:ts/packages/core/src/types/modifiers.types.ts
  • 修饰器底层调用链实现:ts/packages/core/src/models/Tools.ts
  • 修饰器单元测试:ts/packages/core/test/tools/modifiers.test.ts
  • Vercel Provider 工具包装实现:ts/packages/providers/vercel/src/index.ts

【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 15:57:03

ANT9921 H类30W单声道功放芯片深度解析

1. 为什么一块30W单声道功放芯片&#xff0c;值得花一整篇讲清楚&#xff1f; ANT9921这个名字&#xff0c;在音频硬件圈子里不算响亮——它没有TPA3116那种铺天盖地的淘宝爆款标签&#xff0c;也不像MAX98357A那样被树莓派玩家当“默认配置”来用。但如果你真在做一款便携式蓝…

作者头像 李华
网站建设 2026/9/12 15:55:13

微信机器人接口框架/开源

在微信深度渗透私域流量与社群运营的背景下&#xff0c;WTAPI社群机器人API凭借其“高稳定、易开发、强扩展”的技术特性&#xff0c;为开发者提供了覆盖营销系统、智能客服、自定义机器人等核心场景的微信二次开发解决方案。以下结合用户核心需求与WTAPI技术优势&#xff0c;系…

作者头像 李华
网站建设 2026/9/12 15:55:02

车辆行驶过程中如何获得准确位置信息?——GNSS PVT POS 算法(3)

四. 历元间差分算法 在之前的文章中有提到双核或者双任务场景下&#xff0c;针对RTK耗时较长、内存空间存储有限等问题&#xff0c;会在PVT任务中基于RTK上报的高精度定位点信息差分出实时高频的定位结果信息&#xff0c;在此过程中使用到的算法就是历元间差分算法。4.1 载波历…

作者头像 李华