30 August 2026 ยท Alexander Ilg

Writing specs for AI agents

CRMTHREE was built by AI agents working from a written specification. Not "AI-assisted" in the autocomplete sense - agents implemented whole features from the spec while I reviewed, tested, and corrected. That experience taught me what a specification actually needs when the reader is not a colleague who can walk over and ask. Five lessons.

1. Acceptance criteria, not descriptions

Prose describes; criteria decide. The difference shows the moment an agent has to make a call. From the CRMTHREE spec, lead conversion does not say "leads can be converted". It says: the dialog pre-fills these fields from these sources, on conversion these three records are created, the status is set to Converted, these reference fields are populated, the user is navigated to the opportunity - or the contact if there is none - and the lead's owner is inherited by every created record. An agent reading that has no room to improvise, which is exactly the point. Every ambiguity you leave in a spec becomes a decision made by whoever - or whatever - reads it.

Here is what that looks like in the raw spec:

### 3. Lead Management
As a user, I want to capture and qualify leads so that I can
identify new sales opportunities.

**Acceptance Criteria:**
- Leads can be scored (manually via score field 0-100) and
  qualified (status transitions: New → Contacted →
  Qualified/Unqualified → Converted)
- A lead can be converted into a contact, account, and/or
  opportunity via a "Convert Lead" dialog accessible from the
  lead detail page header. The dialog pre-fills: Contact
  (first_name, last_name, email, phone, mobile, position),
  Account (company → name1), and optionally an Opportunity
  (user enters name). On conversion: records are created, lead
  status is set to "Converted", conversion fields are populated
  (converted_contact_id, converted_account_id,
  converted_opportunity_id, converted_at), and the user is
  navigated to the new opportunity (or contact if no
  opportunity). The lead's owner_id is inherited by all
  created records.

Verbatim from specs/specifications.md - markdown a human can review and an agent can execute.

2. Make the data model machine-readable

The single highest-leverage artifact in the repository is data-model.json: every object, field, type, enum, and relationship in one structured file. Agents can load it whole and generate forms, list views, validation, and services from it without guessing a single field name. The prose spec references it instead of repeating it, so there is exactly one source of truth. If you write only one thing for agents, write this.

3. Write down the UX, not just the features

Agents produce UIs quickly - each one a fresh interpretation. Without a UX spec, screen two will not match screen one. CRMTHREE's UX spec defines the patterns once: what a list page is, what a detail page is, where quick actions live, how linked records appear, parents before children. After that, "build the invoice pages" means the pattern applied to invoices - consistency by construction rather than by review.

4. State the constraints that code cannot show

Some of the most important sentences in the architecture spec look boring: API keys never reach the browser, every external call goes through the server-side proxy, no Firebase project identifier is hardcoded in source. A human absorbs such rules from the codebase's vibe. An agent needs them stated, because it will otherwise cheerfully produce the convenient version. Constraints are the part of the design most worth writing down.

5. Specs before code, as a rule the agent knows

The repository's instruction file for agents opens with the project's one hard rule:

ALWAYS update the spec BEFORE changing any implementation - features, modifications, behavior-changing fixes. No exceptions.

This is what keeps the whole model honest over time. The spec stays the product, the code stays the proof, and any drift between them is by definition a bug - findable, because both are written down.

The result of all five is a repository where "anyone can build it" is not a slogan. The spec was precise enough for agents to build the reference implementation - which means it is precise enough for yours.

← All posts