> ## Documentation Index
> Fetch the complete documentation index at: https://smithers-feat-claude-workflow-mirror.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenAPI Tools

> Generate AI SDK tools from an OpenAPI spec. Auth, filtering, observability built in.

`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.

<Note>API reference: [OpenAPI](/reference/openapi) lists every OpenAPI export and option, and links to source and tests.</Note>

```ts theme={null}
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

```ts theme={null}
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

| Export                                                                                            | Purpose                                                                                  |
| ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `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:

```bash theme={null}
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.

```bash theme={null}
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.
