Skip to content

COMMENT conventions

Kozou reads the COMMENT you attach to tables, columns, views, and foreign keys and turns it into three surfaces: an Admin UI, a REST API, and MCP context for AI agents. Most of a COMMENT is plain prose meant for humans, and Kozou carries that prose through untouched. But a small, opt-in set of @-prefixed tags lets you add structure — widget hints, AI guidance, business policy, and example queries — without leaving SQL.

This page documents that tag vocabulary exactly as @kozou/core parses it. For how the parsed result lands in each surface, see Emitted surfaces. For why the database is the single source for all of this, see Postgres as source of truth.

The model: prose first, tags as opt-in structure

Section titled “The model: prose first, tags as opt-in structure”

A COMMENT is plain text. You write it for a human reader, and the first line should be short — Kozou uses it as a fallback label. Below that prose, you may add tag lines. A tag line is recognized when it starts (after optional leading whitespace) with @, a tag name, and a colon:

@<name>: <value>

Four tag names are known to v0.1.1: @ai, @widget, @policy, and @example. Each is parsed differently, and the choices below are deliberate — some tags stay in the displayed body, some are removed, and one is lifted out entirely. The sections that follow cover each tag and what happens to a tag Kozou does not recognize.

The parser returns a single structured result per COMMENT:

type ParsedComment = {
body: string; // human-facing text, with some tags removed
ai: string[]; // every @ai value, in order
widget: WidgetType | null; // the last valid @widget value
policy: string[]; // every @policy value, in order
examples: ExampleQuery[]; // each @example block, lifted out of body
};

@ai carries instructions or context aimed at an AI agent rather than at a UI. You can write more than one @ai line; each value is collected, in order, into ai[].

COMMENT ON TABLE orders IS
'Customer orders. One row per placed order.
@ai: For revenue figures, prefer the view vw_orders_paid.
@ai: Rows where deleted_at is not null are soft-deleted; exclude them.';

@ai is the one tag that is both kept in the displayed body and extracted. The reasoning is that an @ai note usually reads as a sensible sentence to a human as well, so removing it would lose context for anyone reading the raw description. The same text therefore appears in body and in ai[].

@widget tells the Admin UI which input control to render for a column. It is meaningful only on a column COMMENT; on a table or view COMMENT it has no column to bind to.

COMMENT ON COLUMN products.description IS
'Long-form product copy shown on the storefront.
@widget: textarea';

Three behaviors are specific to @widget:

  • It is removed from the displayed body. Unlike @ai, a @widget line is structural noise to a human reader, so it does not appear in body.
  • Last one wins. If a COMMENT contains more than one @widget line, the final valid value is the one that takes effect.
  • The value must be a known widget type. If the value is not one of the types below, Kozou logs a warning and records no widget for that column (so it falls back to the heuristic default).

The full set of widget types, exactly as defined in @kozou/core, is these 12:

text
textarea
number
boolean
date
datetime
enum-select
relation-select
json
image-url
uuid
currency

@widget is a hint, not the only input. When you omit it, Kozou infers a widget from the column’s type and constraints (for example, a column with a CHECK list of allowed values infers enum-select, and a foreign-key column infers relation-select). A YAML UI Hints file, if present, takes precedence over both the @widget tag and the heuristic. image-url renders the image’s URL for display in v0.1.1; it is not an upload control.

@policy — business-policy text (not enforced in v0.1)

Section titled “@policy — business-policy text (not enforced in v0.1)”

@policy records a business rule in prose. Every @policy line is collected into policy[], and — like @ai — the line is kept in the displayed body.

COMMENT ON COLUMN orders.status IS
'Order lifecycle state.
@policy: An order may only move to ''shipped'' after payment is captured.
@widget: enum-select';

In v0.1.1, @policy is parsed but not enforced. Kozou extracts the text and makes it available as context; it does not generate constraints, triggers, or API-layer checks from it. Treat it as documentation that travels with the schema and reaches AI agents, not as a guarantee the runtime upholds.

@example — example queries for views and concepts

Section titled “@example — example queries for views and concepts”

@example attaches a runnable example query to a view (surfaced as a “concept” in MCP). It is the only multi-line tag in v0.1.1, and it has the most distinctive parsing:

  • The text on the @example: line itself is the description (it may be empty).
  • The indented continuation lines below it are the SQL.
  • The block ends at the first non-indented line, the next @-tag, or the end of the COMMENT.
  • The shared leading indentation is stripped, so the stored SQL reads as written rather than indented by the COMMENT block. Blank lines inside the block are preserved, so a multi-statement example keeps its separators.
COMMENT ON VIEW vw_orders_paid IS
'Orders that have been paid for.
@example: Total revenue in the last 30 days
select sum(total_amount)
from vw_orders_paid
where paid_at >= now() - interval ''30 days'';';

Unlike every other tag, an @example block is lifted out of the displayed body entirely. The SQL is surfaced separately — as a list of { description, sql } entries — because it is presented as example queries, not as prose. From the COMMENT above, the body keeps only Orders that have been paid for., and the example becomes one entry whose description is Total revenue in the last 30 days and whose sql is the dedented two-line query.

Unknown tags — kept in the body, logged as a warning

Section titled “Unknown tags — kept in the body, logged as a warning”

If a COMMENT contains a tag Kozou does not recognize — say a future @foo: — the parser does not fail. It keeps the line in the displayed body and logs a warning. This is deliberate forward compatibility: a COMMENT written for a newer Kozou still renders sensibly under v0.1.1, and the unknown text is never silently dropped.

COMMENT ON COLUMN products.sku IS
'Stock-keeping unit.
@foo: reserved for a future convention';

The @foo: line stays in body, and you will see a warning from @kozou/core noting that an unknown tag was kept in the body.

Put the rules together on a single generic column. Suppose you have a products table with a status column constrained to draft, published, or archived:

COMMENT ON COLUMN products.status IS
'Publication state of the product.
draft: not yet visible
published: live on the storefront
archived: hidden but retained
@ai: Only ''published'' rows should appear in public listings.
@widget: enum-select';

Kozou parses that one COMMENT into the following pieces:

Part of the COMMENTWhere it goes
Publication state of the product. and the three draft/published/archived linesbody — the displayed description
@ai: Only 'published' rows should appear in public listings.kept in body and added to ai[]
@widget: enum-selectremoved from body; sets widget to enum-select

So the displayed body reads as plain prose (the type description plus the @ai sentence), the column renders with an enum select control in the Admin UI, and the @ai guidance is available to AI agents through MCP. One COMMENT, three surfaces.

If you had written @widget: dropdown instead, dropdown is not one of the 12 known widget types, so Kozou would log a warning, leave widget unset for that column, and fall back to the inferred default (here, enum-select, because the column has a CHECK list).

The same parsed result feeds all three of Kozou’s outputs:

  • Admin UI (@kozou/svelte-ui) — @widget chooses the input control for a column; the body text becomes the field’s description.
  • REST API — in v0.1.1 the REST layer is provided by PostgREST running alongside Kozou. COMMENT prose is what describes your tables and columns. The v0.2 line adds an experimental in-house REST layer, @kozou/api, behind kozou dev --adapter api; treat it as experimental.
  • MCP context (@kozou/mcp) — @ai notes, @policy text, and @example queries become structured context an AI agent can read, so the agent learns not just your table shapes but the guidance and example query paths you wrote alongside them.

For a surface-by-surface walkthrough of exactly what each output contains, continue to Emitted surfaces.