agentleFS
RBraga01RBraga01/a-team/skills/api-contract-first/SKILL.md

api-contract-first

Skill24 starsChanged 24 days agoMITView on GitHub

Hard gate before implementing any API endpoint or service interface. Requires a written, reviewed contract (OpenAPI 3.x, protobuf, or GraphQL schema) before any implementation code is written. Prevents breaking changes, misaligned clients, and undocumented behaviour.

3 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

7 rules. About 0 are common, 7 are distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈7

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use this skill before writing ANY of these:

    line 18
  2. Distinctive:

    Before implementation begins, verify the contract satisfies all of these:

    line 87
  3. Distinctive:

    If the implementation reveals that the contract needs to change:

    line 123
  4. Distinctive:

    Update the contract first

    line 124
  5. Distinctive:

    Never silently diverge from the contract.

    line 128
  6. Distinctive:

    Write at least one contract test per endpoint that validates the actual response against the OpenAPI schema:

    line 132
  7. Distinctive:

    All of these precede the same outcome: a client built on undocumented assumptions, followed by a breaking change that neither team sees …

    line 154

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

API Contract First

The Law

NO API IMPLEMENTATION WITHOUT A REVIEWED CONTRACT.
Writing endpoints before the contract is building to a spec that doesn't exist.
The contract IS the spec. Code that matches it is correct. Code that doesn't is wrong.

When to Use

Use this skill before writing ANY of these:

  • A new REST endpoint
  • A new gRPC/protobuf service method
  • A new GraphQL query, mutation, or subscription
  • A new event schema (Kafka, SQS, webhooks)
  • A new inter-service interface

The Contract Process

Step 1: Write the Contract

Choose the format that matches the project's stack:

REST → OpenAPI 3.x

# docs/api/openapi.yaml
paths:
  /orders:
    post:
      summary: Create a new order
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrderRequest'
      responses:
        '201':
          description: Order created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Order'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
components:
  schemas:
    CreateOrderRequest:
      type: object
      required: [userId, items]
      properties:
        userId:
          type: string
          format: uuid
        items:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/OrderItem'

Events / Async → AsyncAPI or JSON Schema

# docs/events/order-created.yaml
name: order.created
version: 1.0.0
payload:
  type: object
  required: [orderId, userId, createdAt]
  properties:
    orderId: { type: string, format: uuid }
    userId: { type: string, format: uuid }
    createdAt: { type: string, format: date-time }

Step 2: Contract Review Checklist

Before implementation begins, verify the contract satisfies all of these:

Naming & Consistency

  • Resource names are nouns, plural (/orders not /createOrder)
  • Consistent casing throughout (snake_case for JSON fields, kebab-case for URL segments)
  • New names consistent with existing API vocabulary (don't introduce synonyms for existing concepts)

Completeness

  • All error responses documented (at minimum: 400, 401, 403, 404, 422, 500)
  • All required vs optional fields explicitly marked
  • Field types, formats, and constraints defined (min/max, pattern, enum values)
  • Pagination documented if the endpoint returns a collection

Versioning

  • Breaking changes introduce a new version (/v2/) — never modify /v1/ in a breaking way
  • A change is breaking if it: removes a field, changes a field type, makes an optional field required, changes status code semantics

Security

  • Authentication requirement stated (which scheme: Bearer, API Key, session)
  • Authorisation scope documented (who can call this: any user, admin only, service-to-service)
  • Rate limits noted if applicable

Consumer Perspective

  • The contract was designed for how clients need to use it — not how it's easiest to implement
  • A new team member could implement a client from this contract alone

Step 3: Get Contract Approved

Save the contract file to docs/api/ or docs/events/. The contract is reviewed before implementation begins — not after.

Approval gate: the planner agent must reference the approved contract file in the implementation plan. If no contract file is referenced, the plan is not complete.

Step 4: Implement Against the Contract

Implementation is correct when it matches the contract exactly. The contract is the source of truth — not the implementation.

If the implementation reveals that the contract needs to change:

  1. Update the contract first
  2. Re-review the changed section
  3. Then update the implementation

Never silently diverge from the contract. Every divergence is a breaking change waiting to happen.

Step 5: Contract Tests

Write at least one contract test per endpoint that validates the actual response against the OpenAPI schema:

// [VALID] — tests the real implementation against the contract
import { validate } from 'openapi-validator'
import { spec } from '../docs/api/openapi.yaml'

test('POST /orders response matches contract', async () => {
  const response = await request(app).post('/orders').send(validPayload)
  const errors = validate(spec, '/orders', 'post', response)
  expect(errors).toHaveLength(0)
})

Rationalization Red Flags

These mean you are about to skip the contract step:

  • "The endpoint is simple, I'll document it after"
  • "The client team knows what they're getting"
  • "We'll sort out the contract in the PR description"
  • "It's an internal API, nobody will break"

All of these precede the same outcome: a client built on undocumented assumptions, followed by a breaking change that neither team sees coming.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.