agents icon indicating copy to clipboard operation
agents copied to clipboard

[bugfix]: `createToolsFromOpenAPISpec` function needs to be updated in order to use it with `ai-sdk@^5`

Open yusuf-eren opened this issue 5 months ago • 3 comments

Hey, I realized a problem while using @cloudflare/ai-utils . I know it's a seperate repo but this repo is more relative to the solution i think.

My example project's package.json (cloned from agents-starter and upgraded to ai-sdk v5 and agents@391 pr. ) :

{
  "name": "cloudflare-agent-starter",
  "version": "1.0.0",
  "description": "",
  "type": "module",
  "private": true,
  "scripts": {
    "start": "vite dev",
    "deploy": "vite build && wrangler deploy",
    "test": "vitest",
    "types": "wrangler types",
    "format": "prettier --write .",
    "check": "prettier . --check && biome lint && tsc"
  },
  "keywords": [
    "cloudflare",
    "ai",
    "agents"
  ],
  "author": "",
  "license": "MIT",
  "devDependencies": {
    "@biomejs/biome": "^2.1.4",
    "@cloudflare/vite-plugin": "1.11.4",
    "@cloudflare/vitest-pool-workers": "^0.8.63",
    "@cloudflare/workers-types": "^4.20250813.0",
    "@tailwindcss/vite": "^4.1.11",
    "@types/node": "^24.3.0",
    "@types/react": "^19.1.10",
    "@types/react-dom": "^19.1.7",
    "@vitejs/plugin-react": "^5.0.0",
    "prettier": "^3.6.2",
    "tailwindcss": "^4.1.11",
    "typescript": "^5.9.2",
    "vite": "^7.1.2",
    "vitest": "3.2.4",
    "wrangler": "^4.33.0"
  },
  "dependencies": {
    "@ai-sdk/openai": "^2.0.22",
    "@ai-sdk/react": "^2.0.26",
    "@ai-sdk/ui-utils": "^1.2.11",
    "@cloudflare/ai-utils": "^1.0.1",
    "@phosphor-icons/react": "^2.1.10",
    "@radix-ui/react-avatar": "^1.1.10",
    "@radix-ui/react-dropdown-menu": "^2.1.15",
    "@radix-ui/react-slot": "^1.2.3",
    "@radix-ui/react-switch": "^1.2.5",
    "agents": "https://pkg.pr.new/cloudflare/agents@391",
    "ai": "^5.0.26",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "marked": "^16.1.2",
    "react": "^19.1.1",
    "react-dom": "^19.1.1",
    "react-markdown": "^10.1.0",
    "remark-gfm": "^4.0.1",
    "tailwind-merge": "^3.3.1",
    "workers-ai-provider": "^0.7.3",
    "zod": "^3.25.76"
  }
}

Code

async onChatMessage(onFinish: StreamTextOnFinishCallback<any>) {
    const stream = createUIMessageStream({
      execute: async ({ writer }) => {
        const convertedTools = await createToolsFromOpenAPISpec(
          "https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/3_0/petstore.yaml",
          {
            overrides: [
              {
                matcher: ({ url }) => url.hostname === "petstore.swagger.io",
                values: {
                  headers: { "Content-Type": "application/json" }
                }
              }
            ]
          }
        ).then((tools) => {
          const t = tools.map((tool) => {
            const inputSchema = tool.parameters;
            // const inputSchema = z.object({
            //    data: z.string()
            // });
            const toolFunction = tool.function;
            delete tool.parameters;
            delete tool.function;
            return {
              inputSchema,
              execute: toolFunction,
              ...tool
            };
          });

          return Object.fromEntries(t.map((tool) => [tool.name, tool]));
        });

        const result = streamText({
          messages: convertToModelMessages(this.messages),
          model: openai("gpt-4o"),
          tools: {
            ...convertedTools,
            })
          },
          onFinish: async (args) => {
            await onFinish({
              finishReason: args.finishReason,
              content: args.content,
              text: args.text,
              reasoning: args.reasoning,
              reasoningText: args.reasoningText,
              steps: args.steps,
              totalUsage: args.totalUsage,
              toolCalls: args.toolCalls,
              dynamicToolCalls: args.dynamicToolCalls,
              files: args.files,
              sources: args.sources,
              staticToolCalls: args.staticToolCalls,
              usage: args.usage,
              dynamicToolResults: args.dynamicToolResults,
              staticToolResults: args.staticToolResults,
              toolResults: args.toolResults,
              warnings: args.warnings,
              response: args.response,
              providerMetadata: args.providerMetadata,
              request: args.request
            });
          }
        });

        writer.merge(result.toUIMessageStream());
      }
    });

    return createUIMessageStreamResponse({ stream });
  }

if you replace the inputSchema with a zod object while mapping such as z.object({ data: z.string() }) , it will work.

yusuf-eren avatar Sep 05 '25 12:09 yusuf-eren

@threepointone is working as we speak on updating agents-starter

whoiskatrin avatar Sep 05 '25 13:09 whoiskatrin

right now, to unblock your work, it can be as simple as const inputSchema = jsonSchema(tool.parameters); this should work

whoiskatrin avatar Sep 05 '25 14:09 whoiskatrin

thanks! I will try soon and let you know

yusuf-eren avatar Sep 05 '25 14:09 yusuf-eren