Use an existing OpenAPI document to create a starting AGENTO configuration. The generator reads a local JSON or YAML file, maps supported operations to native tools, and validates the result. Review the generated file before running it against your API.
Generation is an authoring step. It does not call your API or an AI model. AgentRuntime loads the reviewed config and does not need the OpenAPI document at runtime.
Check feature availability
This guide describes the generator in the OpenAPI implementation PR. It requires an agento-runtime release that includes the agento-openapi binary and the agento-runtime/openapi export. It is not part of the 1.0.0 release documented by the rest of this site.
After installing a release that includes the generator, check the local binary:
npm install agento-runtime
npx --no-install agento-openapi --help
If the command is unavailable, check npm ls agento-runtime and the release notes. Installing 1.0.0 again will not add this feature. --no-install prevents npm from trying to download an unrelated package named after the binary.
Prepare the source document
Use a local openapi.json or openapi.yaml describing your actual API. Supported document versions are OpenAPI 3.0.x and 3.1.x. Swagger 2.0 and OpenAPI 3.2 are not accepted.
If your Express or Next.js project has no OpenAPI document, follow Create an OpenAPI document first. Routes, schemas, and sanitized API examples are inputs for preparing that document; the AGENTO generator does not scan application source code.
The following downloadable openapi.yaml describes a public read operation. api.example.com is a placeholder. Replace the host and contract with your actual API before executing a request.
openapi: 3.0.3
info:
title: Services API
version: 1.0.0
servers:
- url: https://api.example.com/v1
paths:
/services/{id}:
get:
operationId: getService
summary: Get a service
description: Return the details of an existing service by its identifier.
parameters:
- name: id
in: path
required: true
schema:
type: string
minLength: 1
- name: locale
in: query
schema:
type: string
enum: [en, ar]
responses:
'200':
description: Service details
Set a unique operationId for each operation. AGENTO uses it as the tool ID. Without one, the generator derives an ID from the method and path; invalid names and collisions fail conversion. Tool IDs and mapped input names must use letters, digits, underscores, or hyphens, start with a letter or underscore, and fit within 64 characters. Credential and prototype-related input names are rejected.
Generate a separate draft
Run the CLI from your project directory:
npx --no-install agento-openapi openapi.yaml --output config.generated.yml
The input can also be openapi.json. --output is required. Parent directories must already exist, and the output file must not exist. The generator refuses to overwrite your reviewed configuration.
The command produces config.generated.yml for the sample above. Inspect it, then save your reviewed version as config.yml. version: "2" is the AGENTO config format, independent of the OpenAPI and npm package versions.
Warnings and errors are written to stderr. Success includes REVIEW_REQUIRED: this is a reminder to review the result, not a conversion failure. A parse, conversion, validation, read, or write failure exits with status 1. Conversion errors produce no partial config.
Choose the server URL
The server URL is the address of your backend API, including any shared prefix such as /v1 or /api. It is the address AGENTO will call after you review the generated config and run it. It is independent of the AGENTO documentation website and the AI model provider.
For an existing endpoint https://api.example.com/v1/services/42, split the address into a server URL and an operation path:
| Part | Value |
|---|---|
| Server URL | https://api.example.com/v1 |
| OpenAPI path | /services/{id} |
Generated request.url | https://api.example.com/v1/services/{id} |
The {id} placeholder stays in the config; the runtime fills it from the reviewed path mapping when you invoke the tool. Do not repeat the shared prefix in both parts: server /v1 plus path /v1/services/{id} produces /v1/v1/services/{id}.
In the source document, define the backend address under servers. This is only the server fragment; keep the operations from your full OpenAPI document:
servers:
- url: https://api.example.com/v1
To generate a draft for a different environment without editing that source document, supply --base-url:
npx --no-install agento-openapi openapi.yaml --output config.staging.yml --base-url https://staging.example.com/v1
This writes https://staging.example.com/v1/services/{id} into the generated request. The option overrides all server definitions, including servers declared on individual operations. If your operations use separate backends, check every generated URL before using a global override. In JavaScript, the corresponding option is generateConfig(source, { baseUrl: "https://staging.example.com/v1" }).
Without an override, the generator selects a server separately for each operation: operation-level servers first, then path-level servers, then root servers. A level explicitly set to servers: [] does not fall back to a parent. The selected list must contain exactly one server; it does not automatically choose the first of several servers.
| Source situation | What to do |
|---|---|
| One absolute server for the intended environment | Generate without --base-url. |
| Production and staging are both listed | Pass the intended environment's full base URL; there is no server-index selector. |
Server is absent, empty, or relative, such as /api | Pass an absolute URL, including the backend's actual base path. |
Server uses variables, such as {region} | Declared string defaults are used; --base-url supplies a complete replacement when needed. |
Use an absolute HTTP(S) URL without embedded credentials, query parameters, fragments, or unresolved variables. Use HTTPS for production. The generator makes no network request and cannot prove that the address is reachable or that its routes match your API. Review the emitted request.url values and test the reviewed config against your intended environment.
The URL is saved in the YAML when you generate it. Changing an OpenAPI server later does not change an existing config or a running runtime. Generate a separate candidate file, compare it with your reviewed config, and deploy the reviewed changes as described under Update your API without losing reviewed settings.
Review the generated tools
| Source document | Generated configuration |
|---|---|
operationId | Tool id. |
summary and description | Tool title and description. Missing descriptions fall back to method and path. |
| Path parameters | Inputs under path; mapping such as id: $.path.id. |
| Query parameters | Inputs under query; mapping such as locale: $.query.locale. |
| Header parameters | Inputs under headers; explicit header mappings. |
| JSON object body | Inputs under body; one mapping per top-level property. Nested JSON values remain intact. |
| Required parameter | Required inside its input group; the group becomes required if it contains any required parameter. |
| GET / HEAD | read-only, without confirmation. |
| POST / PUT / PATCH | side-effect, with confirmation required. |
| DELETE | destructive, with confirmation required. |
For the sample, the generated request contains this fragment:
request:
method: GET
url: https://api.example.com/v1/services/{id}
auth:
type: none
map:
path:
id: $.path.id
query:
locale: $.query.locale
headers: {}
body: {}
This is a fragment, not a complete config. The downloadable output also contains the tool input schema and behavior.
Review the tools you want to expose, their descriptions, required inputs, target URLs, and effects. Remove operations you do not want the agent to offer. Conversion processes all declared operations and fails if any consumed feature is unsupported; it does not silently skip operations or offer an operation-selection flag.
The generator does not infer models, dependencies, selection/navigation, routing hints, or response output schemas. Add these through the normal configuration, response, and workflow options. A response schema in OpenAPI is not copied into response.output_schema.
HTTP methods provide an initial effect policy, not a guarantee about your API. Review any GET endpoint that changes application state. Generated writes require confirmation, but their preview starts empty; add readable user-facing facts using confirmation settings.
Run the reviewed configuration
Save the run.mjs example beside the reviewed config.yml:
import { AgentRuntime } from "agento-runtime";
const id = process.argv[2];
if (!id) throw new Error("Usage: node run.mjs <existing-service-id>");
const runtime = await AgentRuntime.create({
configPath: "./config.yml",
presentation: "raw",
});
try {
const result = await runtime.invoke({
sessionId: "openapi-example",
tool: "getService",
arguments: { path: { id }, query: { locale: "en" } },
});
console.log(JSON.stringify(result, null, 2));
if (result.status !== "completed") process.exitCode = 1;
} finally {
runtime.dispose();
}
node run.mjs EXISTING_SERVICE_ID
Use an identifier from your API, and compare the returned data with a direct request. The nested path and query objects match generated input groups; { id: "123" } alone does not match this tool. The relative config path is resolved from the process working directory. Deploy the reviewed config with your backend.
This direct call needs no model. For natural-language chat(), configure a conversation model or supply a model adapter when creating the runtime. In your application, bind sessionId to the caller and handle continuation states as described in runtime results; the fixed session ID in this one-shot example is not an application session strategy.
Configure authentication
HTTP bearer security maps to request.auth.type: session. Pass the authenticated user's token through auth.token on runtime requests. The generator neither obtains nor validates that token. Downstream authorization remains your API's responsibility.
A header API key requires an explicit environment variable name:
npx --no-install agento-openapi openapi.yaml --output config.generated.yml --api-key-env CatalogKey=CATALOG_API_KEY
CatalogKey must match the name in components.securitySchemes, not the HTTP header name. CATALOG_API_KEY is the name of a server environment variable, not its secret value. The key's value is required at runtime startup; it is not needed for generation. Repeat --api-key-env for different schemes used by different operations.
Operation security: [] disables inherited security. Basic, OAuth/OIDC, cookie/query API keys, multiple alternatives, and combined security schemes are unsupported by this converter. Never remove real authentication requirements to make conversion succeed. For an unsupported scheme, author the integration using the normal authentication contract.
Credential-bearing requests require HTTPS. For local testing, any insecure transport opt-in belongs in the reviewed config; the generator has no flag to enable it.
Supported inputs and limits
| Area | Supported scope |
|---|---|
| References | Local #/... JSON Pointers used by consumed paths, parameters, request bodies/schemas, and security schemes. No external or recursive refs. |
| Parameters | Non-null scalar path/header values, scalar query values, and repeated scalar query arrays (form with explode: true, including its default). |
| JSON bodies | A single application/json media type. A non-null object with named properties, explicit additionalProperties: false, and at least one required property. |
| Schema constraints | Explicit types, properties, required fields, enums/const, numeric/string/array/object constraints, and recognized formats, subject to native config validation. |
| Nullable values | Supported in JSON body properties. Nullable URL/header parameter values and a nullable whole body are unsupported. |
| OpenAPI 3.0 normalization | nullable and boolean exclusive numeric bounds are converted to the native schema format. |
No multipart/form-data, form-encoded/scalar/array bodies, GET/HEAD bodies, object parameters, CSV query arrays, deepObject, allowReserved: true, or allowEmptyValue: true. Unsupported schema semantics include composition (allOf, anyOf, oneOf), defaults, boolean schemas, input fields with readOnly: true, custom formats, and newer JSON Schema dialect keywords. OPTIONS, TRACE, callbacks, and webhooks are also unsupported.
For example, a supported POST body can declare:
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required: [name]
properties:
name:
type: string
minLength: 1
The native mapper cannot emit an empty JSON object body or preserve arbitrary top-level body fields. The converter rejects body schemas that permit those cases. Do not tighten your documented API schema unless that constraint accurately describes the operation you intend to expose; use manual AGENTO configuration where the existing mapper can represent the operation. Cases outside the mapper itself require an HTTP integration change or an additional execution capability.
Numeric formats such as int32 and int64 are omitted as annotations; declare explicit bounds when needed. Examples, XML metadata, vendor extensions, and reference summary/description overrides are not converted into runtime behavior. OpenAPI generation/conversion does not prove that the deployed API implements the documented contract.
Resolve conversion errors
| Diagnostic | What to check |
|---|---|
PARSE_ERROR | Invalid JSON/YAML, duplicate keys, or excessive YAML aliases. |
UNSUPPORTED_VERSION | Export OpenAPI 3.0 or 3.1. |
INVALID_DOCUMENT, INVALID_SCHEMA, INVALID_PARAMETER, INVALID_BODY | Fix the declaration at the reported source path. |
SERVER_SELECTION_REQUIRED, INVALID_SERVER | Supply an absolute --base-url; do not embed credentials, query, or a fragment in the server URL. |
DUPLICATE_OPERATION_ID, INVALID_OPERATION_ID, UNSUPPORTED_NAME | Use unique compatible names. Keep credentials out of model input properties. |
PATH_PARAMETER_MISMATCH | Every {id} placeholder needs a matching required in: path parameter, with no extra path mappings. |
UNSUPPORTED_REFERENCE, INVALID_REFERENCE, UNRESOLVED_REFERENCE, CYCLIC_REFERENCE | Bundle external refs, fix local pointers, or simplify recursive schemas. Validation siblings on references are unsupported. |
UNSUPPORTED_SERIALIZATION, UNSUPPORTED_PARAMETER, UNSUPPORTED_BODY, UNSUPPORTED_SCHEMA | Use a representable contract or author native config manually. Do not delete meaningful constraints just to pass conversion. |
UNSUPPORTED_SECURITY, API_KEY_ENV_REQUIRED, UNSUPPORTED_HEADER | Review security definitions and environment names. Reserved or conflicting transport headers cannot become model inputs. |
UNSUPPORTED_METHOD, UNSUPPORTED_CALLBACKS, UNSUPPORTED_WEBHOOKS, NO_OPERATIONS, INVALID_OPERATION | Check the declared operations against the supported scope. |
CONFIG_VALIDATION_FAILED | Read the embedded AGENTO error code and correct schema constraints, mapping, names, or transport settings. |
EEXIST | The output file already exists. Choose a new draft filename; keep the reviewed config. |
ENOENT | Check the input file and output parent directory. Paths are relative to the current directory. |
Conversion stops at the first error. Correct it and rerun. The output directory remains untouched by conversion failures; filesystem write failures are separate errors.
Use the JavaScript API
The optional agento-runtime/openapi entry point exposes generateConfig(source, options). Download generate-config.mjs:
import { readFile, writeFile } from "node:fs/promises";
import { generateConfig } from "agento-runtime/openapi";
const result = generateConfig(await readFile("openapi.yaml", "utf8"));
for (const diagnostic of result.diagnostics) {
console.error(diagnostic);
}
if (!result.ok) {
process.exitCode = 1;
} else {
await writeFile("config.generated.yml", result.yaml, { flag: "wx" });
}
Optional settings are baseUrl and apiKeyEnv, for example { baseUrl: "https://api.example.com/v1", apiKeyEnv: { CatalogKey: "CATALOG_API_KEY" } }.
On success, result contains ok: true, config, yaml, and diagnostics. On failure, it contains ok: false and diagnostics, without config or YAML. Each diagnostic contains severity, code, path, and message. The API accepts text, performs no file I/O, and makes no network/model calls.
Update your API without losing reviewed settings
Keep the source document and reviewed config in version control. After an API contract change, regenerate into a new filename, such as config.candidate.yml, compare it with config.yml, and merge intentional changes. The CLI has no overwrite, append, or automatic merge mode.
Keep your model configuration, confirmation previews, response schemas, dependencies, and presentation settings when reviewing the diff. Test affected operations against staging, then deploy the reviewed config and a pinned package version together. Do not regenerate automatically at application startup. Continue with production readiness.