YAML Frontmatter Schema

February 26, 2026 · View on GitHub

Canonical Schema (all card types)

Every card MUST have this structure. Fields marked (auto) are managed by memory-engine.py. Fields marked (required) must be written by the agent when creating a card.

---
# ── identity ──
type: crm                    # (required) crm | lead | contact | project | personal | daily | note
description: >-              # (required) One-line summary. What is this card about?
  Cloud infrastructure provider, enterprise tier, renewal Q2 2026

# ── classification ──
tags: [cloud, enterprise, renewal] # (required) 2-5 freeform tags for grep filtering
status: active                # (required) universal: active|draft|pending|done|inactive; CRM-only: prospect|negotiation|won|lost
industry: SaaS                # (optional) For CRM/leads
region: US                    # (optional) ISO country codes
source: referral              # (optional) How this entity entered the system
priority: High                # (optional) High | Medium | Low

# ── ownership ──
owner: agent                  # (optional) Who owns this relationship
responsible: agent            # (optional) Who is doing the work

# ── dates ──
created: 2026-01-15           # (recommended) When card was first created
updated: 2026-02-20           # (recommended) When content was last meaningfully changed

# ── deal tracking ──
deal_status: negotiation       # (optional) For active deals
deal_deadline: 2026-03-15     # (optional) Deal close date

# ── memory system (auto) ──
last_accessed: 2026-02-25     # (auto) When card was last read/touched
relevance: 0.85               # (auto) 0.0-1.0, decays over time
tier: active                  # (auto) core | active | warm | cold | archive
---

Required Fields Explained

description (string, one line)

The single most important field for search quality. Write a concise summary that answers: "If someone searches for this entity, what should they see in results?"

Good: "Cloud infrastructure provider, enterprise tier, renewal Q2 2026" Bad: "contact" (too vague) Bad: (empty — defeats the purpose of the entire system)

tags (list, 2-5 items)

Cross-cutting labels for fast grep filtering. Use lowercase, hyphens.

tags: [hot-lead, ai-training, enterprise, follow-up]

Search: grep -rl "hot-lead" vault/crm/

type (enum)

TypeWhen
crmExisting client/company
leadPotential client
contactPerson (not a lead/client)
projectActive or past project
personalFamily, friends
dailyDaily log file
noteEverything else

status (enum, normalized)

Domain-specific lifecycle. NOT the same as tier (which is memory-system lifecycle).

Universal (all card types):

StatusMeaning
activeCurrently relevant, in use, engaged
draftWork in progress, not finalized
pendingWaiting for external input or decision
doneCompleted, kept for reference
inactiveWas active, went quiet or outdated

CRM-specific (only for type: crm, lead, client):

StatusMeaning
prospectIdentified lead, no deep engagement yet
negotiationProposal sent, in talks
wonDeal closed positively
lostRejected, didn't pursue

ONLY these 9 values. No mixed case, no free-text.

Typical lifecycle by type:

  • crm/lead: prospect → active → negotiation → won/lost
  • project: draft → active → done
  • contact: active → inactive
  • note/knowledge: draft → active → inactive (outdated)
  • personal: active → inactive
  • daily: no status needed (has date field)

When in doubt: CRM → prospect, everything else → active.

Memory System Fields (auto-managed)

relevance (float, 0.0-1.0)

Computed by decay engine. Do not manually edit unless marking as core.

  • 1.0 = just accessed
  • 0.5 = ~33 days old
  • 0.1 = floor (60+ days)

tier (enum)

Computed by decay engine based on last_accessed.

  • core — only manually assigned, never auto-demoted. Use for: identity, security rules, pricing, critical reference.
  • active — 0-7 days since access. Searched in all modes.
  • warm — 8-21 days. Searched in normal+ modes.
  • cold — 22-60 days. Deep search only.
  • archive — 60+ days. Creative mode or explicit queries.

last_accessed (ISO date)

Updated by touch command (graduated: +1 tier per touch).

Agent Protocol for New Cards

When creating ANY new card:

  1. ALWAYS include: type, description, tags, status
  2. Write description as if it's a search result snippet — concise, informative
  3. Add 2-5 tags that cross-cut directory structure
  4. Run memory-engine.py touch <file> after creation
  5. The engine will auto-add relevance, last_accessed, tier on next decay run

Field Semantics

type (string)

Auto-inferred from directory path if not present. Configurable via type_inference in .memory-config.json.

tags (list)

Freeform. Useful for cross-cutting concerns that don't fit directory structure.

tags: [hot-lead, ai-training, enterprise, follow-up]

Search: grep -rl "hot-lead" vault/crm/

Configuration

Type inference mapping in .memory-config.json:

{
  "type_inference": {
    "crm/clients/": "crm",
    "crm/leads/": "lead",
    "contacts/": "contact",
    "projects/": "project"
  }
}

When memory-engine.py init encounters a file without type, it checks the file path against these patterns.

Frontmatter Tips

  1. Don't duplicate content. If the H1 heading says "# Acme Corp", you don't need title: Acme Corp — the engine infers it.
  2. Tags > nested directories. A flat crm/ with tags is more flexible than crm/hot/enterprise/ai/.
  3. Status is domain-specific. The memory system uses tier for lifecycle; status is for your business logic (active/won/lost/churned).
  4. updated vs last_accessed: updated = when content changed; last_accessed = when anyone read it. Both matter for decay; the engine uses whichever is most recent.