Skip to main content
createOpenApiTools parses an OpenAPI 3.x spec and returns AI SDK tools, one per operation, with Zod schemas converted from the spec’s JSON schemas.
API reference: OpenAPI lists every OpenAPI export and option, and links to source and tests.
import { ToolLoopAgent } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { createOpenApiTools } from "smithers-orchestrator/openapi";

const tools = await createOpenApiTools("./petstore.json", {
  baseUrl: "https://api.petstore.example.com",
  auth: { type: "bearer", token: process.env.PETSTORE_TOKEN! },
});

const agent = new ToolLoopAgent({
  model: anthropic("claude-fable-5"),
  tools,
});

Options

type OpenApiToolsOptions = {
  baseUrl?: string;                  // overrides spec.servers[0].url
  headers?: Record<string, string>;  // merged into every request
  auth?:
    | { type: "apiKey"; name: string; in: "header" | "query"; value: string }
    | { type: "bearer"; token: string }
    | { type: "basic"; username: string; password: string };
  include?: string[];                // operationId allowlist
  exclude?: string[];                // operationId blocklist
  namePrefix?: string;               // prefix generated tool names
  operations?: Record<
    string,
    | false
    | {
        include?: boolean;           // false skips this operation
        name?: string;               // agent-facing tool name
        description?: string;        // agent-facing tool description
        responseExamples?: Array<{
          status?: string | number;
          description?: string;
          value: unknown;
        }>;
      }
  >;
};
Pass the spec itself as the first argument to createOpenApiTools(input, options). input may be a parsed spec object, file path, URL, or raw OpenAPI text.

Public API

ExportPurpose
createOpenApiTools(input, options?) / createOpenApiToolsSync(input, options?)Build a record of AI SDK tools keyed by operationId.
createOpenApiTool(input, operationId, options?) / createOpenApiToolSync(...)Build one operation as a tool.
listOperations(input)Return parsed operation metadata without creating tools.
extractOperations(spec)Extract operations from an already parsed spec.
loadSpecEffect(input)Load and parse a spec from object, path, URL, or raw text.
loadSpecSync(input)Load and parse a spec from object, local file path, or raw text. It does not fetch URLs.
jsonSchemaToZod(schema, spec, visited?) / buildOperationSchema(parameters, requestBody, spec)Lower-level schema conversion helpers.

CLI

Generate a reusable AI SDK tools module:
bunx smithers-orchestrator openapi generate ./api/openapi.yaml ./src/openapi-tools.js
The generated module imports createOpenApiToolsSync, creates the tools from the spec, and exports them as both tools and the default export.
bunx smithers-orchestrator openapi list ./api/openapi.yaml
openapi list previews every operationId, method, path, and summary. Useful for auditing what an agent will be able to call before wiring it up.

What gets generated

For each operation:
  • A Zod schema for the request body + path/query/header parameters.
  • An execute(args) function that performs the HTTP call.
  • The operation’s summary / description becomes the tool description.

Response handling

  • JSON responses are parsed and returned as objects.
  • Non-JSON responses are returned as strings.
  • HTTP status codes are not special-cased by the tool factory; if the server returns a JSON or text error body, that body is returned to the agent.
  • Request failures, fetch failures, and schema/tool execution exceptions are returned as { error: true, message, status: "failed" } so the agent can react in its loop.

Filtering

include / exclude accept arrays of operationId. If both are set, exclude wins. Useful for limiting an agent’s surface area to a specific feature (“just the inventory endpoints”). namePrefix prefixes generated tool names without changing the operationIds used for filtering. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name. Use operations for per-operation curation keyed by the original operationId. Set an entry to false or { include: false } to skip that endpoint, set name to rename the generated tool, set description to replace the spec summary/description with agent-facing instructions, and add responseExamples to append concrete response shapes to the tool description. This lets a connector expose a small curated set instead of dumping every endpoint as an agent-callable tool. include / exclude still use the original operationId, not the curated name.

Observability

OpenAPI tool calls update the exported Effect metrics (openApiToolCallsTotal, openApiToolCallErrorsTotal, openApiToolDuration) and carry Effect log annotations/spans with the operation id, method, and path. The current tool factory does not emit OpenApiToolCalled onto the Smithers run event bus; that event variant is typed/categorized for future event-bus integration.

Notes / Limitations

  • Schema composition (allOf, anyOf, oneOf) is supported; converts to Zod unions/intersections.
  • Nullable fields and defaults from the spec are preserved.
  • Cookie parameters are ignored when generating tool input schemas and requests.
  • JSON request bodies are the only request body media type generated today; non-JSON bodies such as form data, multipart uploads, and binary payloads are not encoded.
  • Parameter serialization styles are not implemented. Path parameters are URL-encoded and substituted directly, and query parameters are sent with default URLSearchParams serialization.
  • Swagger 2.0 objects are not supported as a first-class input format. Use OpenAPI 3.x specs with openapi, paths, and info fields.