Search docs

Jump between documentation pages.

AI-friendly route metadata

Pass an optional meta field on any route() call to attach structured usage examples, extra descriptive copy, or free-form x-*extensions. Daloy validates every example against your route’s Standard Schema at build time and emits the same payload into OpenAPI (examples on the request body, examples on the matching response, x-daloy-examples on the operation) and into the daloy inspect --ai dump that codegen agents and SDK builders consume.

Additive and non-breaking. Existing routes keep working unchanged — meta is optional everywhere.

Author examples

ts
import { App } from "@daloyjs/core";
import { z } from "zod";

const app = new App();

const Book = z.object({ id: z.string(), title: z.string() });

app.route({
  method: "POST",
  path: "/books",
  operationId: "createBook",
  tags: ["Books"],
  request: { body: z.object({ title: z.string().min(1) }) },
  responses: {
    201: { description: "Created", body: Book },
    400: { description: "Invalid" },
  },
  meta: {
    description: "Create a book record.",
    tags: ["AI"],
    examples: {
      happy: {
        summary: "Standard create",
        request: { body: { title: "Dune" } },
        response: { status: 201, body: { id: "1", title: "Dune" } },
      },
      missingTitle: {
        summary: "Validation failure",
        request: { body: { title: "" } },
        response: { status: 400 },
      },
    },
    extensions: {
      "x-codegen-hint": "books-table",
    },
  },
  handler: async ({ body }) => ({
    status: 201 as const,
    body: { id: crypto.randomUUID(), title: body.title },
  }),
});

Shape of a meta block

  • summary / description / tags — augment the route-level fields of the same name. Route-level values win when both are set; tags are de-duplicated and concatenated.
  • examples — record of named { summary?, description?, request?: { params?, query?, headers?, body? }, response?: { status, body?, headers? } } pairs. Every field is optional individually; pass only the parts you want documented.
  • extensions — free-form bag emitted onto the OpenAPI Operation Object. Keys without an x- prefix are prefixed automatically for spec compliance.

Build-time validation

Run pnpm daloy inspect --check (or call runContractTests(app) from your tests). For every named example, Daloy validates:

  • request.body / request.query / request.params / request.headers against the matching schema on request when both sides exist.
  • response.body against the response schema for the declared status; an unknown status code is itself an error.

Mismatches fail the contract run so the OpenAPI document never publishes a sample that does not match its schema.

OpenAPI surfacing

The same shape is folded into the generated OpenAPI 3.1 document so Swagger UI, Scalar, and Hey API see your examples without any extra wiring:

json
{
  "paths": {
    "/books": {
      "post": {
        "operationId": "createBook",
        "tags": ["Books", "AI"],
        "x-codegen-hint": "books-table",
        "x-daloy-examples": { "happy": { /* ... */ } },
        "requestBody": {
          "content": {
            "application/json": {
              "schema": { "type": "object", "properties": { "title": { "type": "string" } } },
              "examples": {
                "happy": { "summary": "Standard create", "value": { "title": "Dune" } }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": { "$ref": "..." },
                "examples": {
                  "happy": { "summary": "Standard create", "value": { "id": "1", "title": "Dune" } }
                }
              }
            }
          }
        }
      }
    }
  }
}

daloy inspect --ai

Dump the whole route catalog — with JSON Schema for every input and output and every meta.examples entry — as a single, self-describing JSON document. It is the format Daloy recommends for feeding to an LLM or a codegen agent that needs more than the OpenAPI spec alone:

bash
pnpm daloy inspect --ai > routes.json
pnpm daloy inspect --ai --json | jq '.routes[].operationId'

# Emit YAML instead of JSON — typically ~30% smaller, which matters
# when you are pasting the dump into an LLM system prompt.
pnpm daloy inspect --ai --yaml > routes.yaml
pnpm daloy inspect --ai --format yaml > routes.yaml

# Combine with --tag/--method to scope the dump
pnpm daloy inspect --ai --tag Books

Output shape:

json
{
  "daloy": { "ai": 1 },
  "generatedAt": "2026-05-19T12:00:00.000Z",
  "routeCount": 1,
  "routes": [
    {
      "method": "POST",
      "path": "/books",
      "operationId": "createBook",
      "tags": ["Books", "AI"],
      "request":  { "body": { /* JSON Schema */ } },
      "responses": {
        "201": { "description": "Created", "body": { /* JSON Schema */ } },
        "400": { "description": "Invalid" }
      },
      "examples": { "happy": { /* same shape you authored */ } },
      "extensions": { "x-codegen-hint": "books-table" }
    }
  ]
}

YAML output

Both --ai and --openapi accept --yaml (shorthand) or --format yaml. The emitter is a tiny built-in YAML 1.2 serializer with no runtime dependencies. Because YAML drops braces, commas, and most quotes, the dump is typically about 30% smaller than the equivalent pretty-printed JSON — a meaningful saving when the file becomes part of an LLM system prompt.

yaml
daloy:
  ai: 1
generatedAt: "2026-05-19T12:00:00.000Z"
routeCount: 1
routes:
  - method: POST
    path: /books
    operationId: createBook
    tags:
      - Books
      - AI
    request:
      body:
        type: object
        properties:
          title:
            type: string
        required:
          - title
    responses:
      "201":
        description: Created
        body:
          type: object
          properties:
            id: { type: string }
            title: { type: string }
      "400":
        description: Invalid
    examples:
      happy:
        summary: Standard create
        request:
          body:
            title: Dune
        response:
          status: 201
          body:
            id: "1"
            title: Dune
    extensions:
      x-codegen-hint: books-table

Use JSON when piping to jq or any other JSON-only tool, and YAML when humans or LLMs will read the file directly.

Consuming the dump

The dump is intentionally a flat JSON file with no DaloyJS runtime coupling. Feed it directly to:

  • Hey API codegen as a sibling artifact: the examplesmap carries through to the generated SDK’s docstrings.
  • An LLM (Claude / GPT / Gemini) as part of a system prompt for “write me a fetch call that hits the books endpoint”.
  • A custom code generator (Python client, Go SDK, Postman collection) — every field is plain JSON.

Pair this page with the CLI inspector guide and the OpenAPI generation guide for the broader contract-first picture.