Connect OpenAPI services
Connect a service that publishes an OpenAPI specification to a ToolRegistry, so each operation becomes a tool the agent can call.
Prerequisites
Section titled “Prerequisites”- A ToolRegistry, or a manifest you are about to create, attached to an AgentRuntime through
spec.toolRegistryRef. See Adding tools to agents. - A PromptPack you can edit. The pack decides which tools the model is offered.
- A specification URL (OpenAPI v2 or v3) that serves JSON and that the runtime can fetch when the agent starts. YAML specifications are not parsed.
Add an openapi handler
Section titled “Add an openapi handler”An openapi handler is self-describing. You give it the specification URL and the runtime builds one tool per operation, named after the operation ID. An operation with no ID is named <method>_<path>, for example get_users_id. You do not write a tool definition.
apiVersion: omnia.altairalabs.ai/v1alpha1kind: ToolRegistrymetadata: name: api-toolsspec: handlers: - name: petstore type: openapi openAPIConfig: specURL: https://petstore.swagger.io/v2/swagger.json baseURL: https://petstore.swagger.io/v2baseURL overrides the server URL in the specification. Without it, the runtime uses the first servers URL (OpenAPI 3) or scheme://host plus basePath (Swagger 2, scheme defaults to https), and fails to connect if neither exists.
Limit the operations
Section titled “Limit the operations”An empty operationFilter exposes every operation. List operation IDs to expose only those:
openAPIConfig: specURL: https://petstore.swagger.io/v2/swagger.json baseURL: https://petstore.swagger.io/v2 operationFilter: - getPetById - findPetsByStatusHow arguments reach the service
Section titled “How arguments reach the service”Each tool’s input schema lists the operation’s parameters and the top-level properties of its JSON request body. The runtime sends each argument where the specification declares it:
| Declared as | Sent as |
|---|---|
in: path | Substituted into the path, URL-escaped. . and .. are refused |
in: query | A query-string parameter |
in: header | A request header of the same name |
| Anything else | The JSON request body for POST, PUT and PATCH; query-string parameters for other methods |
For PUT /pets/{petId}, the arguments {"petId": "7", "name": "Rex"} become PUT /pets/7 with the body {"name": "Rex"}.
A pack that declares its own schema for the tool can nest the request body under a single body argument instead: {"petId": "7", "body": {"name": "Rex"}} sends the same request. The runtime unwraps body only when it is an object, it is the only argument that is not a declared parameter, and the operation declares no parameter or body property named body.
Declare the operations in the pack
Section titled “Declare the operations in the pack”The runtime offers the model only the tools that a PromptPack prompt lists in tools. It does not add ToolRegistry tools to the pack, so an openapi handler on its own offers the model nothing. List each operation ID the prompt may call:
"prompts": { "main": { "id": "main", "tools": ["getPetById", "findPetsByStatus"] }}Publish the change as described in PromptPack. For a pack held in a ConfigMap, re-apply the ConfigMap. The operator rolls the agent pod when the pack content changes.
Combine handler types in one registry
Section titled “Combine handler types in one registry”A ToolRegistry holds any mix of handler types. Each handler keeps its own configuration:
spec: handlers: - name: search type: http httpConfig: endpoint: https://api.search.com/query method: POST tool: name: web_search description: "Search the web" inputSchema: type: object properties: query: type: string required: [query]
- name: code-assistant type: mcp mcpConfig: transport: sse endpoint: http://mcp-code.tools.svc.cluster.local/sse
- name: weather-api type: openapi openAPIConfig: specURL: https://api.weather.com/openapi.jsonVerify
Section titled “Verify”kubectl get toolregistry api-tools -o jsonpath='{.status.phase}'The phase is Ready when every handler validates and every discovered tool is available. An openapi handler reports one placeholder entry in status.discoveredTools, named after the handler. The individual operations are discovered when the agent starts, so check the runtime logs for the OpenAPI adapter connected line to see how many operations loaded.
A registry tool that no prompt lists in tools is not offered to the model. The runtime logs it once at startup, and sets the AgentRuntime condition PackContentValid to False:
kubectl logs deployment/<agent> -c runtime | grep "NOT declared by the pack"kubectl get agentruntime <agent> -o jsonpath='{.status.conditions[?(@.type=="PackContentValid")].message}'The log line reads ToolRegistry tools are NOT declared by the pack and will not be offered to the model and lists the tool names under tools. The condition message names the same tools. When every tool is declared, PackContentValid is True.
Related pages
Section titled “Related pages”- ToolRegistry reference for every
openAPIConfigfield - Connect MCP servers
- Authenticate tools
- Test a tool before wiring it to an agent