ViteHub is still experimental. Expect bugs and breaking changes.

OpenAPI

Expose selected OpenAPI operations as bounded Agent tools or a generated Capability CLI.

openapi() turns selected OpenAPI operationIds into bounded HTTP operations. Use it to generate Agent tools from a known API contract instead of writing one fetch() tool per endpoint.

Attaching the Capability is the opt-in. Channel, customer, or tenant admission belongs in access(), Agent Trigger routing, or separate Agent Definitions, not in openapi().

Configure an OpenAPI Capability

Add openapi() to the Agent when every invocation needs the API, or to one Channel's capabilities when only that Channel needs it.

server/agents/support.ts
import { defineAgent } from 'vite-hub/agent'
import { access, openapi } from 'vite-hub/agent/capabilities'

export default defineAgent({
  driver: { model },
  capabilities: [
    access({
      chat: {
        resolve({ invoker }) {
          return invoker.kind === 'portal'
        },
      },
    }),
    openapi({
      spec: 'https://portal.example.com/_openapi.json',
      operations: ['portalProductSearch', 'portalPurchaseOrders'],
    }),
  ],
})

By default, openapi() creates one model-facing tool per selected operation. Each tool uses the OpenAPI request path, query parameters, request body schema, operation summary, and response parser.

When cli is set, ViteHub replaces those operation tools with one Capability CLI tool. The generated CLI has one subcommand per selected operation and can also run through vitehub agent dev --cli.

Select operations

Always pass the operation allowlist directly. ViteHub does not expose every operation by default.

server/agents/support.ts
openapi({
  spec: 'https://billing.example.com/openapi.json',
  operations: ['billingListCustomers', 'billingGetInvoice'],
})

Unsupported HTTP methods are ignored unless the operation is selected. In v1, selected operations can use GET, HEAD, or POST.

Configure requests

ViteHub derives the request server from the OpenAPI document by default:

  1. servers[0].url
  2. the OpenAPI spec URL origin

Use hooks.request for runtime auth, cookies, tenant values, body additions, query additions, and timeout changes. The hook receives the selected operation, Agent Capability context, visible model input, and a mutable draft request. When the hook owns OpenAPI fields such as tenant path params or runtime body tokens, declare them in provides; ViteHub removes those fields from the model and generated CLI schemas, strips them from caller input, then validates the final prepared request after the hook runs.

server/agents/support.ts
openapi({
  spec: 'https://portal.example.com/_openapi.json',
  operations: ['portalProductSearch', 'portalPurchaseOrders'],
  hooks: {
    request: {
      provides: {
        body: ['cubeToken'],
        path: ['tenantId'],
      },
      async handler({ context, operation, request }) {
        const session = context.get<{
          cubeToken: string
          tenantId: string
          token: string
        }>('portalSession')
        if (!session) throw new Error('Portal session missing.')

        request.headers.set('authorization', `Bearer ${session.token}`)
        request.path.tenantId = session.tenantId

        if (operation.id === 'portalPurchaseOrders') {
          request.body = {
            ...(request.body as Record<string, unknown> | undefined),
            cubeToken: session.cubeToken,
          }
        }
      },
    },
  },
})

ViteHub still keeps caller-owned required fields in the model and generated CLI schemas. If the hook only provides tenantId, another required path param such as orderId remains required from the caller.

For a broken, missing, or environment-neutral servers entry, use server as an override escape hatch. server can also be a callback when the override comes from the current Agent Invocation context.

server/agents/support.ts
openapi({
  spec: './openapi.json',
  server: 'https://preview.example.com/api',
  operations: ['listCustomers'],
})

Generate a Capability CLI

Use cli to give agents and developers the same operation catalog as commands.

server/agents/support.ts
openapi({
  spec: 'https://billing.example.com/openapi.json',
  operations: ['billingListCustomers', 'billingGetInvoice'],
  cli: {
    name: 'billing',
    description: 'Inspect live billing API data.',
  },
})

cli can also resolve from the current Agent Invocation. Return false or undefined to omit the generated CLI for that invocation without detaching the OpenAPI Capability or changing its lifecycle.

server/agents/support.ts
openapi({
  spec: 'https://portal.example.com/_openapi.json',
  operations: ['portalProductSearch', 'portalPurchaseOrders'],
  cli: ({ run }) => run?.channelId === 'portal'
    ? {
        name: 'portal-api',
        description: 'Inspect live Portal data.',
      }
    : false,
})

Treat Channel metadata as an availability hint, not authorization. Check trusted request, Agent Actor, or access() evidence before privileged API calls.

Run the generated CLI through the Agent Dev Loop. Agents expose generated Capability CLI Contributions by default. Use defineAgent({ cli: { capabilities: false } }) to attach the OpenAPI Capability without exposing its CLI.

Terminal
pnpm vitehub agent dev --url http://localhost:3000 --agent support --cli billing -- list-customers --json

Shape responses

Use transformResponse when the raw API response contains transport fields or verbose provider-specific rows.

server/agents/support.ts
openapi({
  spec: 'https://billing.example.com/openapi.json',
  operations: ['billingGetInvoice'],
  transformResponse(response, { operation, response: http }) {
    return {
      operationId: operation.id,
      status: http.status,
      data: response,
    }
  },
})

Driver support

Agent DriverSupport
Model-backedReceives selected OpenAPI tools, or one generated Capability CLI tool when cli is set.
Provider-backedReceives selected OpenAPI tools, or the generated Capability CLI tool, through the provider MCP bridge.
Custom-run-backedReceives prepared context; driver.run decides whether to call API operations directly.

Options

OptionTypeDefaultDescription
specstring | URL | object | functionrequiredOpenAPI document URL, inline document, or invocation-scoped document resolver.
operationsreadonly string[]requiredSelected OpenAPI operationIds exposed by this Capability.
descriptionstringnonePrefix for generated operation-tool descriptions and fallback description for the generated Capability CLI.
hooks.request(context) => patch | void or { provides?, handler }noneFetch-style request preparation hook for runtime headers, cookies, path, query, body, and timeout values.
hooks.request.provides{ body?, path?, query? }noneRuntime-owned OpenAPI input fields to remove from model and generated CLI schemas before caller validation.
serverstring | URL | functionOpenAPI serverOverride escape hatch for specs without a usable servers[0].url or spec URL origin.
clifalse | { name, description? }falseGenerates a Capability CLI instead of one model-facing tool per operation.
responseType"json" | "text""json"Response parser for operation results.
transformResponse(response, context) => outputnoneMaps parsed operation responses before returning them to the Agent.
specHeadersRecord<string, string>noneHeaders used only when fetching the OpenAPI document.
timeoutnumbernoneDefault request timeout in milliseconds.