---
name: schema-rules
description: Critical rules for creating and updating entities — enum discovery, field types, common pitfalls
loading: eager
---

# Entity Schema Rules

These rules apply whenever you create or update entries. For the full field reference, load the `entity-schema` skill.

## Golden Rules

**Only pass fields you have real values for.** Do not include optional fields like `deal_value`, `email`, `website`, `start_date`, etc. unless you have an actual value. Never pass empty strings for optional fields — omit them entirely from the `data` object.

**Never wrap the `content` parameter in quotes.** The `content` field is raw markdown, not a JSON string. Do not add leading or trailing `"` characters. Pass the markdown directly.

## Enum Fields — Always Check the Schema

Many entity fields are enums (a closed set of allowed values). Field names that signal an enum include `stage`, `status`, `category`, `priority`, `audience`, `source`, `type`. **Do not guess enum values from memory.** Allowed values change as the product evolves, and a guessed value that "sounds right" (e.g. `negotiating` vs the actual `negotiation`) will fail validation.

**Before writing any enum-shaped field on create or update:**

1. Call `get_entity_schema(entityType)` to fetch the authoritative schema for the entity type.
2. Inspect the returned `fields` object. For each enum field, the descriptor includes:
   - `type: "enum"` (or `"enum[]"` for arrays of enums)
   - `enum: [...]` — the full list of allowed values
   - `default: ...` — the value applied when the field is omitted (when present)
3. Use only values from the `enum` array. If you want the default, omit the field entirely.

You may cache the schema response within a single conversation turn, but re-fetch when starting work on a different entity type or after a schema change is mentioned.

## Field Types (from `get_entity_schema`)

- `string` — free text
- `string` with format `url` — must be a valid URL with protocol (e.g., `https://example.com`)
- `string` with format `email` — must be a valid email
- `datetime` — ISO 8601 datetime (auto-stamped on `created_at` / `updated_at` — do not pass these)
- `number` — actual number, not a quoted string
- `boolean` — `true` / `false`
- `enum` — one of the values listed under the field's `enum` array
- `string[]` — array of strings; for wikilink arrays (`attendees`, `services`, etc.) each entry is a wikilink id like `[[acme-corp]]`
- `enum[]` — array of enum values; each entry must be one of `itemEnum`

Dates use exactly two fields. `date` (type `date`) is every entity's salient date — its meaning is type-specific and shown in the field's `label` (a task's "Due date", a deal's "Close date", a project's "End date"). `start_date` (type `date`, only on project/event/task/deliverable/deal) is the optional earlier bound of a range `[start_date, date]`. Both must be `YYYY-MM-DD` (date-only — not a datetime) or omitted; anything else is rejected.

## Error Recovery

When an entry creation or update fails with a validation error, read the message carefully:

- If it names an enum field (e.g. `stage: Invalid enum value`), call `get_entity_schema` for that entity type, pick a valid value from the `enum` list, and retry.
- If it complains about a URL or email format, drop the field rather than substituting a placeholder.
- If it complains about a missing required field, ask the user or omit the entry and explain.

Do not skip the entry silently — either retry with corrected data or tell the user what went wrong.
