Composio JSON Schema 转 Zod 实战指南:将工具输入 Schema 安全转换为运行时校验器 📅 发布时间:2026/9/12 16:19:04 👁 浏览次数: Composio JSON Schema 转 Zod 实战指南将工具输入 Schema 安全转换为运行时校验器【免费下载链接】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导读本指南基于 Composio 仓库中的 json-schema-to-zod 示例 展开讲解如何用 Composio SDK 将工具Tool的 JSON Schema 输入参数转换为 Zod Schema从而获得 TypeScript 类型安全的运行时校验能力。读完本文你将掌握如何初始化 Composio 客户端、如何按 slug 拉取任意工具的原始输入 Schema、如何借助jsonSchemaToZodSchema与zod-to-json-schema完成双向转换以及转换链路背后$ref解析、严格模式等底层实现细节。示例项目结构示例项目位于 ts/examples/json-schema-to-zod其目录结构如下ts/examples/json-schema-to-zod/ ├── .env.example # 环境变量模板COMPOSIO_API_KEY ├── CHANGELOG.md # 版本变更记录 ├── README.md # 示例说明 ├── package.json # 依赖与脚本定义 ├── tsconfig.json # TypeScript 编译配置 └── src/ └── index.ts # 示例入口拉取工具 → Schema 转换其中 package.json 声明了start与dev两个核心脚本分别用于直接运行和监听模式运行运行时采用 Bunscripts: { start: bun src/index.ts, dev: bun --watch src/index.ts, typecheck: tsc --noEmit -p ./tsconfig.json }依赖方面composio/core以workspace:*形式引入即当前仓库内的核心 SDK 包同时引入zod-to-json-schemaZod → JSON Schema 反向转换与dotenv加载环境变量。一、环境准备与项目初始化1. 安装依赖在 ts/examples/json-schema-to-zod 目录下执行pnpm install由于composio/core是通过 pnpm workspace 引入的本地包安装时 pnpm 会自动将其链接到仓库内的 ts/packages/core 源码便于在示例中直接使用最新 SDK 实现。2. 配置环境变量复制环境变量模板并填写 API Keycp .env.example .env编辑.env填入你的 API Key# Composio API Key - Get it from https://app.composio.dev COMPOSIO_API_KEYyour_composio_api_key_here # Add other environment variables as needed for your example # OPENAI_API_KEYyour_openai_api_key_here # ANTHROPIC_API_KEYyour_anthropic_api_key_here关键变量变量说明获取方式COMPOSIO_API_KEYComposio 平台 API 密钥用于鉴权与工具拉取Composio Dashboard示例 .env.example 中有注明OPENAI_API_KEY/ANTHROPIC_API_KEY仅在你需要接入对应 LLM Provider 时按需补充各模型厂商控制台3. 运行示例# 直接运行 pnpm start # 开发模式文件变更后自动重启 pnpm devdev脚本通过 Bun 的--watch标志实现文件监听修改src/index.ts后无需手动重启。二、示例代码逐行拆解示例入口 src/index.ts 的核心流程只有三步初始化 SDK → 拉取工具 Schema → 转换为 Zod 再转回 JSON Schema 验证。1. 初始化 Composio SDKimport { Composio, jsonSchemaToZodSchema } from composio/core; import { zodToJsonSchema } from zod-to-json-schema; import dotenv/config; const composio new Composio({ apiKey: process.env.COMPOSIO_API_KEY, });Composio是 SDK 的顶层客户端apiKey直接取自process.env.COMPOSIO_API_KEY由dotenv/config负责把.env注入环境。jsonSchemaToZodSchema与Composio均从composio/core导出该函数定义于 ts/packages/core/src/utils/jsonSchema.ts并在 ts/packages/core/src/index.ts 中对外导出。2. 拉取工具并打印原始输入参数const tool await composio.tools.getRawComposioToolBySlug(GOOGLECALENDAR_PATCH_EVENT); console.log(JSON.stringify(tool.inputParameters, null, 2));getRawComposioToolBySlug(slug)按工具 slug例如GOOGLECALENDAR_PATCH_EVENT从 Composio API 拉取工具的完整元数据与 Schema。其底层实现位于 ts/packages/core/src/models/Tools.ts内部调用this.client.tools.retrieve(slug, ...)发起 API 请求支持通过options.version或 SDK 配置的toolkitVersions指定工具版本拿到原始响应后会经过transformToolCases将字段转为 camelCase与applyDefaultSchemaModifiers应用默认 Schema 修饰器你也可以传入options.modifySchema回调在返回前对 Schema 做自定义加工——回调会收到{ toolSlug, toolkitSlug, schema }三个参数拉取失败时抛出ComposioToolNotFoundError请求被取消时抛出ComposioRequestCancelledError。inputParameters即该工具输入参数的 JSON Schema形如{ type: object, properties: { calendarId: { type: string }, eventId: { type: string } }, required: [calendarId, eventId] }3. JSON Schema → Zod → JSON Schema 的转换闭环const zodSchema jsonSchemaToZodSchema(tool.inputParameters ?? {}); console.log(JSON.stringify(zodToJsonSchema(zodSchema), null, 2));jsonSchemaToZodSchema把inputParametersJSON Schema转换为 Zod 运行时对象z.ZodTypeAnyzodToJsonSchema来自zod-to-json-schema再将 Zod Schema 转回 JSON Schema 并打印。这一步的意义在于Zod Schema 既是运行时校验器可用safeParse校验 LLM 或用户传入的参数又是类型推导源通过z.infertypeof zodSchema获得静态类型同时还能无损地导回 JSON Schema 供其他框架使用。jsonSchemaToZodSchema的签名与行为见 ts/packages/core/src/utils/jsonSchema.tsexport function jsonSchemaToZodSchemaT extends z.ZodTypeAny( jsonSchema: Recordstring, unknown, { strict }: { strict?: boolean } { strict: false } ): Tstrict: false默认完整保留所有属性strict: true先调用removeNonRequiredProperties移除所有非必填属性并将additionalProperties置为false仅保留required中声明的字段——适合对 Schema 约束要求严格的场景。三、转换原理从 JSON Schema 到 Zod 的底层实现1. 核心转换器jsonSchemaToZodcomposio/core的转换能力封装自独立的 composio/json-schema-to-zod 包其入口 ts/packages/json-schema-to-zod/src/json-schema-to-zod.ts 定义了两个导出函数export const jsonSchemaToZod (schema: JsonSchema, options: JsonSchemaToZodOptions {}): z.ZodType { const parsedSchema parseSchema(schema, { path: [], seen: new Map(), root: schema, ...options }); return requiresWholeSchemaValidation(schema) ? withWholeSchemaValidation(schema, parsedSchema) : parsedSchema; }; export const jsonSchemaToZodShape (schema, options): SimpleZodRawShape { // 返回 { name: z.string(), age: z.number() } 形式的 raw shape };两个函数的分工jsonSchemaToZod返回完整的ZodType通常是ZodObject适合直接用z.infer推导类型或整体校验jsonSchemaToZodShape返回SimpleZodRawShapeRecordstring, ZodTypeAny适合需要传入 raw shape 的 API——例如 Claude Agent SDK 的tool()函数。转换由parseSchema驱动的解析器parser体系完成。该包在 ts/packages/json-schema-to-zod/src/parsers 下按 JSON Schema 关键字拆分了一组解析器parse-object、parse-array、parse-string、parse-number、parse-enum、parse-const、parse-all-of、parse-any-of、parse-one-of、parse-not、parse-if-then-else、parse-nullable、parse-null、parse-boolean、parse-multiple-type、parse-typeless-constraints、parse-literal-values等分别处理对象、数组、组合allOf/anyOf/oneOf、条件if/then/else、多类型联合等场景再通过parse-schema统一分发。2. 转换选项JsonSchemaToZodOptions参考 ts/packages/json-schema-to-zod/src/types.ts转换选项如下export type JsonSchemaToZodOptions { withoutDefaults?: boolean; // 是否忽略 default 关键字 withoutDescribes?: boolean; // 是否忽略 description 描述 parserOverride?: ParserOverride; // 自定义解析器覆盖 depth?: number; // 递归深度限制 };parserOverride包 README 中称overrideParser的语义是传入一个函数它接收当前 Schema 节点和引用对象refs当它想替换默认输出时返回一个 Zod 类型否则返回undefined以使用默认解析逻辑const zodSchema jsonSchemaToZod(schema, { parserOverride: (schemaNode, refs) { if (schemaNode.type string schemaNode.format date) { return z.string().date(); // 自定义日期解析 } return undefined; // 其余节点走默认解析 }, });3. 转换前的 Schema 预处理从 Composio API 拉取的 Schema 往往包含$ref、缺失type的对象节点、重复的required条目等问题ts/packages/core/src/utils/jsonSchema.ts 为此提供了一系列预处理工具dereferenceJsonSchema源码位置内联解析内部$ref指针#/$defs/...与#/definitions/...使返回的 Schema 可安全交给不识别引用的消费者如 AJV 等。关键行为外部引用http://、https://、file://等不会被解析仅记录告警日志后原样保留循环引用cycle用哨兵值{ type: object, additionalProperties: true }打断内部引用无法解析时默认抛出JsonSchemaRefResolutionError传入{ onUnresolved: sentinel }则替换为哨兵节点并注入说明文字Schema shape unresolved at the source — validate loosely.适合处理来自无法编辑的上游服务的 Schema例如部分 API 工具的输出参数声明了$ref却未提供$defs受MAX_REF_CHAIN_DEPTH 100引用链深度与MAX_NODE_DEPTH 512节点深度双重保护超限即抛错会过滤__proto__、constructor、prototype等污染性键防止原型污染攻击采用 Draft 2020-12 语义$ref的兄弟关键字siblings在与目标合并时优先保留。ensureObjectTypeOnProperties源码位置为所有携带properties但未显式声明type的对象节点补上type: object。原因是 OpenAI 容忍省略而 Google Gemini 严格遵循 OpenAPI 3.0会拒绝缺少type的嵌套对象声明。deduplicateJsonSchemaRequiredArrays源码位置对required数组去重。重复条目在 JSON Schema 2020-12 中非法但语义不变保留首次出现即可。toStrictJsonSchema源码位置面向 OpenAI 结构化输出strict: true的归一化。其核心策略与产物每个对象的所有属性都进入required并设置additionalProperties: false原本可选的属性被加宽为可接受nulltype: [string, null]或追加anyOf分支以此模拟可选字段模型传入的null表示省略执行前由omitNullToolArguments剔除oneOf转为anyOfdefault/examples被剥离无法表达的构造allOf、prefixItems、patternProperties、布尔子 Schema、外部或悬空$ref等会被收集进unsupported数组——此时调用方应放弃 strict 模式发送原 Schema每次重写都记录在changes上限 50 条与totalChanges中便于审计。omitNullToolArguments源码位置递归删除工具 Schema 本身不接受null的参数值省略语义而保留原 Schema 本就允许的null如清除该字段的显式语义。removeNonRequiredProperties源码位置即strict: true时调用的裁剪函数——只保留required中列出的属性并设置additionalProperties: false。四、错误处理与边界情况示例的main()对转换链路做了整体 try/catchtry { // 拉取工具 Schema 转换 } catch (error) { console.error(❌ Error running example:, error); process.exitCode 1; }实际开发中除了网络错误与 API 鉴权错误外还需要关注两类 Schema 相关异常JsonSchemaToZodErrorjsonSchemaToZodSchema转换失败时抛出见 ts/packages/core/src/utils/jsonSchema.ts错误信息中会附带触发问题的属性路径cause 中命名了出错的属性便于定位单个畸形属性JsonSchemaRefResolutionErrordereferenceJsonSchema遇到无法解析的内部$ref时抛出错误信息包含ref指针与修复建议确保$ref指针匹配$defs/definitions中的路径、SDK 不解析外部$ref指针等。五、自定义与扩展README 指出示例的核心价值是演示用法业务逻辑需要自行实现。扩展方向包括接入更多应用把getRawComposioToolBySlug(GOOGLECALENDAR_PATCH_EVENT)换成任意工具 slug如GITHUB_CREATE_ISSUE、SLACK_SEND_MESSAGE或遍历composio.tools提供的工具列表批量处理实现业务逻辑用转换出的zodSchema.safeParse(args)校验 LLM 生成的参数或通过z.infer获得静态类型辅助开发加入错误处理与日志区分工具不存在ComposioToolNotFoundError、Schema 转换失败JsonSchemaToZodError与引用解析失败JsonSchemaRefResolutionError三类错误并分别处理结合严格模式若目标 LLM Provider 支持结构化输出可在转换前调用dereferenceJsonSchematoStrictJsonSchema归一化 Schema再配合omitNullToolArguments清洗模型输出。六、运行结果预期成功运行时控制台会依次输出启动提示 Starting Json-schema-to-zod Example...GOOGLECALENDAR_PATCH_EVENT工具的原始inputParameters格式化 JSON经jsonSchemaToZodSchema转换、再由zodToJsonSchema还原的 JSON Schema格式化 JSON——对比前后两份输出可以直观看到转换与还原的保真度提示 Implement your json-schema-to-zod logic here!等待你补充自定义实现。失败时如 API Key 无效、工具 slug 不存在、Schema 无法转换示例会打印❌ Error running example:并设置进程退出码为 1。七、相关示例延伸仓库提供了多个可对照学习的示例OpenAI 示例即 ts/examples/openai展示与 OpenAI 的集成方式LangChain 示例即 ts/examples/langchain展示与 LangChain 的集成方式示例总览即 ts/examples浏览全部可用示例。此外json-schema-to-zod 转换能力的独立包源码位于 ts/packages/json-schema-to-zod其完整测试用例可参考 ts/packages/core/test/utils/jsonSchema.test.ts覆盖dereferenceJsonSchema、toStrictJsonSchema、jsonSchemaToZodSchema等核心函数。结语通过本文你已掌握 Composio 中JSON Schema → Zod → JSON Schema的完整转换链路从初始化 SDK、按 slug 拉取工具 Schema到使用jsonSchemaToZodSchema获得可校验、可推导类型的 Zod 对象并理解了底层$ref解析、对象类型补全、required去重与严格模式归一化等预处理细节。这套能力让开发者可以在 LLM 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创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考