Connect an OpenAPI API
An agent reaches an HTTP API by declaring it, not by coding against it. Point a
connection at an OpenAPI 3.0 or Swagger 2.0 document and every operation you
allow becomes a tool, named after its operationId.
Add a connection
Section titled “Add a connection”Create a file under connections/:
kind = "openapi"spec = "open-meteo.json"operations.allow = ["getForecast"]| Key | Type | Description |
|---|---|---|
kind |
string | Must be openapi. |
spec |
string | An https:// URL, or a path resolved relative to the agent directory. |
base_url |
string | Overrides the spec’s own servers/host for the calls tools make. Supports ${VAR} expansion. |
operations.allow |
string[] | Surface only these operations. Empty (the default) surfaces all of them. |
operations.block |
string[] | Drop these operations. Applied after allow. |
headers |
table | Sent with every request. Values support ${VAR} expansion. |
Operation ids are matched after sanitizing them to tool-name form, so
Journey.Meta in a spec is written Journey_Meta — or either spelling, since
both sides are sanitized before comparison.
Prefer a local spec
Section titled “Prefer a local spec”spec accepts a URL, but a file beside the agent is the better default. A
remote spec means the agent cannot list its own tools without a network round
trip, and if that host is down the connection degrades quietly to no tools
rather than to an error — the agent still starts, just without the capability.
Vendoring the document keeps startup deterministic; the calls themselves still
go to the live API.
Authenticate
Section titled “Authenticate”Credentials are referenced by name and resolved from the environment at load time, so the token lives in your secret store rather than in the folder:
kind = "openapi"spec = "https://api.example.com/openapi.json"operations.allow = ["listInvoices", "getInvoice"]headers = { Authorization = "Bearer ${EXAMPLE_API_TOKEN}" }A ${VAR} with no value in the environment fails the load with the variable’s
name, rather than sending an empty header and getting a puzzling 401.
Narrow the surface
Section titled “Narrow the surface”Filter deliberately. A large public spec can carry hundreds of operations, and
each one spends room in the model’s tool list and widens what a confused model
can reach. operations.allow is the allowlist; operations.block subtracts
from whatever survived it.
Only GET-style read operations are safe to expose without thought — an
allowed deleteAccount is a tool the model can call.
Run it
Section titled “Run it”Connections are established at load time, and maiden logs the resulting tool set:
maiden run my-agent "what is the weather in London?"# [maiden] agent 'my-agent' tools [getForecast]From there an OpenAPI tool is dispatched exactly like a WASM tool, an MCP tool or a subagent — see How maiden fits together.
Related
Section titled “Related”- Connect an MCP server — the other connection kind
- Add a sandboxed tool — when you need code, not a call