openApiTools()
turns that document into one typed tool per API operation, so an agent can call
the API without a hand-written defineTool() per endpoint and without the raw
http tool. Operations that change data ask for
approval by default.
openApiTools is exported from @lousho/build-ai-agent and
@lousho/build-ai-agent/tools. It needs no extra package.
Quick start
openApiTools() is always async, because the document may be a URL. It returns
an array of tools you pass to createAgent({ tools }) like any other.
document can be a parsed OpenAPI 3.0 or 3.1 object, a JSON or YAML string, or
an https URL (a string or a URL). Parsing happens once, inside
openApiTools(); a tool’s execute only builds and sends a request.
What each tool looks like
Accept, Content-Type and Authorization header parameters are ignored, as
the OpenAPI specification says; use bearerToken or headers for credentials.
Options
op is { name, operationId?, method, path, summary?, tags }.
Approval defaults
Withapproval: 'mutating', GET, HEAD and OPTIONS run, and every other method
asks. Each tool also carries MCP-style annotations: readOnlyHint: true, destructiveHint: false on GET, HEAD and OPTIONS; readOnlyHint: false on the
rest, with destructiveHint: true for DELETE. Anything that reads annotations treats these tools the way it treats MCP tools.
Values your application supplies
providedArguments fills parameters the model should not choose, such as a
tenant id. A provided key is removed from the tool’s input schema (the model
never sees it) and added to the request. The value can be a function, called per
request with the operation and the tool call id.
body for the request body). A key that no
selected operation has throws, so a typo does not silently expose the parameter
to the model.
Security rules
- The base URL is yours, not the model’s. The model chooses parameter and
body values; it never chooses the host. The base URL must be https. Plain
http is accepted only for
localhost,127.0.0.1and[::1], and a URL with a user name or password is refused. The same rule applies to a document URL. - Credentials stay out of what the model and your logs see. Headers and
tokens are never part of a tool’s input schema, its
tool.startandtool.doneevents or the transcript; only the model’s own input and the response are. A header the model supplies for a declared header parameter never replacesheadersorbearerToken. - Redirects stay on the base origin. Requests use manual redirects: at most 3 are followed, and only to the same origin as the base URL. A redirect to another origin is a tool error, so a token never leaves the configured origin.
- Path values stay in their segment. Path parameters are percent-encoded
(
../admincannot climb out of its segment), and a value of exactly.or..is refused. - No private-address check. The tools call the base URL you configured. If
that URL can resolve to an internal address that you do not control, put a
proxy in front or pass your own
fetch. Thehttptool’s address checks are for model-chosen URLs.
Large APIs
An API with hundreds of operations is hundreds of tools. Give the agent the ones it needs withinclude or exclude, or with a predicate on op.tags:
Limits
- OpenAPI 3.0 and 3.1 only. A Swagger 2.0 document throws a
ConfigurationErrorthat asks you to convert it first. - Request bodies must be JSON (
application/jsonor+json). An operation with only a multipart, form or XML body is left out; naming it inincludethrows. - Only the first
serversentry is used, with variables at their defaults. Path-level and operation-levelserversare ignored. - Every
$refmust be local (#/components/...); a reference to another file or URL throws. Bundle the document first. - No OAuth flows.
bearerTokenandheaderscover static and per-request credentials. - Response bodies are read as text, and responses are not streamed.