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)
| Type | When |
|---|---|
| crm | Existing client/company |
| lead | Potential client |
| contact | Person (not a lead/client) |
| project | Active or past project |
| personal | Family, friends |
| daily | Daily log file |
| note | Everything else |
status (enum, normalized)
Domain-specific lifecycle. NOT the same as tier (which is memory-system lifecycle).
Universal (all card types):
| Status | Meaning |
|---|---|
active | Currently relevant, in use, engaged |
draft | Work in progress, not finalized |
pending | Waiting for external input or decision |
done | Completed, kept for reference |
inactive | Was active, went quiet or outdated |
CRM-specific (only for type: crm, lead, client):
| Status | Meaning |
|---|---|
prospect | Identified lead, no deep engagement yet |
negotiation | Proposal sent, in talks |
won | Deal closed positively |
lost | Rejected, 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
datefield)
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:
- ALWAYS include:
type,description,tags,status - Write
descriptionas if it's a search result snippet — concise, informative - Add 2-5
tagsthat cross-cut directory structure - Run
memory-engine.py touch <file>after creation - The engine will auto-add
relevance,last_accessed,tieron 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
- Don't duplicate content. If the H1 heading says "# Acme Corp", you don't need
title: Acme Corp— the engine infers it. - Tags > nested directories. A flat
crm/with tags is more flexible thancrm/hot/enterprise/ai/. - Status is domain-specific. The memory system uses
tierfor lifecycle;statusis for your business logic (active/won/lost/churned). updatedvslast_accessed:updated= when content changed;last_accessed= when anyone read it. Both matter for decay; the engine uses whichever is most recent.