A Better Way to Prepare APIs for Agents

Turn { your } OpenAPI specs into efficient, customizable skills for reliable agent actions.

When an AI agent needs to act in the real world, it calls an API. The question isn't whether — it's how to give it the right context.

Current approaches hit a wall

MCP Servers

Write adapter code. Spin up a sidecar process. Manage another runtime. For each API, the integration tax is steep — and you haven't written any business logic yet.

Full Spec in Prompt

Paste the entire Swagger file into the prompt. Thousands of tokens consumed. The agent sees everything, focuses on nothing. Accuracy drops as the spec grows.

So teams build their own

It's a reasonable instinct — slice the spec, curate the context, write a script to automate it. It works for a while. But as APIs evolve and more teams need it, the maintenance cost compounds and the solution rarely travels well.

openapi-to-skills

Converts OpenAPI specifications into focused, executable skill units — shrinking context, eliminating glue code, and improving accuracy.

github-rest-api.yaml 11 MB · 1,078 ops
openapi: 3.0.3
info:
  title: GitHub REST API
  version: 1.1.4
  description: |
    GitHub's v3 REST API for managing
    repositories, issues, pull requests,
    and more.
servers:
  - url: https://api.github.com
    description: Production
paths:
  /repos/{owner}/{repo}/issues:
    get:
      tags:
        - Issues
      summary: List repository issues
      operationId: issues/list-for-repo
      parameters:
        - name: owner
          in: path
          required: true
          schema:
            type: string
        - name: repo
          in: path
          required: true
          schema:
            type: string
        - name: state
          in: query
          schema:
            type: string
            enum: [open, closed, all]
            default: open
        - name: labels
          in: query
          schema:
            type: string
        - name: sort
          in: query
          schema:
            type: string
            enum: [created, updated, comments]
        - name: direction
          in: query
          schema:
            type: string
            enum: [asc, desc]
        - name: per_page
          in: query
          schema:
            type: integer
        - name: page
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/issue'
    post:
      tags:
        - Issues
      summary: Create an issue
      operationId: issues/create
      parameters:
        - name: owner
          in: path
          required: true
          schema:
            type: string
        - name: repo
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [title]
              properties:
                title:
                  type: string
                body:
                  type: string
                assignees:
                  type: array
                  items:
                    type: string
                milestone:
                  type: integer
                labels:
                  type: array
                  items:
                    type: string
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/issue'
        '403':
          description: Forbidden
        '404':
          description: Not Found
  /repos/{owner}/{repo}/issues/{issue_number}:
    get:
      tags:
        - Issues
      summary: Get an issue
      operationId: issues/get
      parameters:
        - name: owner
          in: path
          required: true
          schema:
            type: string
        - name: repo
          in: path
          required: true
          schema:
            type: string
        - name: issue_number
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/issue'
    patch:
      tags:
        - Issues
      summary: Update an issue
      operationId: issues/update
      parameters:
        - name: owner
          in: path
          required: true
          schema:
            type: string
        - name: repo
          in: path
          required: true
          schema:
            type: string
        - name: issue_number
          in: path
          required: true
          schema:
            type: integer
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                body:
                  type: string
                state:
                  type: string
                  enum: [open, closed]
                labels:
                  type: array
                  items:
                    type: string
                assignees:
                  type: array
                  items:
                    type: string
  /repos/{owner}/{repo}/pulls:
    get:
      tags:
        - Pulls
      summary: List pull requests
      operationId: pulls/list
      parameters:
        - name: owner
          in: path
          required: true
          schema:
            type: string
        - name: repo
          in: path
          required: true
          schema:
            type: string
        - name: state
          in: query
          schema:
            type: string
            enum: [open, closed, all]
        - name: head
          in: query
          schema:
            type: string
        - name: base
          in: query
          schema:
            type: string
        - name: sort
          in: query
          schema:
            type: string
        - name: per_page
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: OK
    post:
      tags:
        - Pulls
      summary: Create a pull request
      operationId: pulls/create
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [title, head, base]
              properties:
                title:
                  type: string
                head:
                  type: string
                base:
                  type: string
                body:
                  type: string
                draft:
                  type: boolean
  /search/issues:
    get:
      tags:
        - Search
      summary: Search issues and pull requests
      operationId: search/issues-and-pull-requests
      parameters:
        - name: q
          in: query
          required: true
          schema:
            type: string
        - name: sort
          in: query
          schema:
            type: string
        - name: order
          in: query
          schema:
            type: string
            enum: [asc, desc]
        - name: per_page
          in: query
          schema:
            type: integer
      responses:
        '200':
          description: OK
  /repos/{owner}/{repo}:
    get:
      tags:
        - Repos
      summary: Get a repository
      operationId: repos/get
      parameters:
        - name: owner
          in: path
          required: true
          schema:
            type: string
        - name: repo
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: OK
components:
  schemas:
    issue:
      type: object
      properties:
        id:
          type: integer
        number:
          type: integer
        title:
          type: string
        state:
          type: string
          enum: [open, closed]
        body:
          type: string
        html_url:
          type: string
        user:
          $ref: '#/components/
            schemas/simple-user'
        labels:
          type: array
          items:
            $ref: '#/components/
              schemas/label'
        assignees:
          type: array
          items:
            $ref: '#/components/
              schemas/simple-user'
        milestone:
          $ref: '#/components/
            schemas/milestone'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        closed_at:
          type: string
          format: date-time
    simple-user:
      type: object
      properties:
        login:
          type: string
        id:
          type: integer
        avatar_url:
          type: string
        html_url:
          type: string
    label:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        color:
          type: string
    milestone:
      type: object
      properties:
        id:
          type: integer
        number:
          type: integer
        title:
          type: string
        state:
          type: string
2,026 files
github-v3-rest-api/
├── SKILL.md
└── references/
├── authentication.md
├── resources/ 43
├── schemas/ 904
└── operations/ 1,078
├── gists-create.md
├── issues-create.md
├── issues-get.md
├── issues-list.md
└── 1,074 more…
POST /repos/{owner}/{repo}/issues
Resource issues Operation ID issues/create

Create an issue

Any user with pull access to a repository can create an issue. If issues are disabled, the response will be a 410 Gone status.

Request Body

Required Yes Content Type application/json

Responses

201 Response
403 Forbidden
404 Not Found
422 Validation failed

Success Schema issue

01

Precise Context

Only the relevant operation, parameters, and schemas. The context window stays lean — agents see exactly what they need.

02

Zero Glue Code

No adapters. No sidecar processes. No extra runtime to manage. Generate once, use everywhere.

03

Always in Sync

API spec updated? Re-run the tool. Skills reflect the latest endpoints without manual edits or drift.

One command

$ npx openapi-to-skills generate --input your-api.yaml --output ./skills

Go further

Filter by tags or paths, override output templates, or embed the converter directly into your build pipeline.

Filter

Include or exclude by tags, paths, or deprecated status.

--include-tags
users repos issues
--exclude-paths
/internal
--exclude-deprecated
on

Custom Templates

Override Eta templates to control exactly what each skill file contains.

issues-create.md
# POST /repos/{owner}/{repo}/issues
**Create an issue**
Any user with pull access can create an issue.
+**Internal:** Use PROJECT-123 key format.
+See runbook: /wiki/github-integration

Programmatic API

Embed into build pipelines or custom tooling directly.

build.ts
import { convertOpenAPIToSkill }
  from 'openapi-to-skills';

await convertOpenAPIToSkill(spec, {
  outputDir: './skills',
  parser: {
    filter: {
      includeTags: ['users', 'repos'],
      excludeDeprecated: true,
    },
  },
});
View on GitHub