Skip to main content

memory-schema

Manage Basic Memory schemas: find unschemaed notes, infer and edit schemas, validate notes, detect drift. Use when structured note types (Task, Person, Meeting) need consistency across the graph.

Source facts

Repository
basicmachines-co/basic-memory
Last source activity
October 29, 2026 at 00:59
Detected SKILL.md language
English
Stars
4,447
Forks
345

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
memory-schema
description
Manage Basic Memory schemas: find unschemaed notes, infer and edit schemas, validate notes, detect drift. Use when structured note types (Task, Person, Meeting) need consistency across the graph.
# Memory Schema Manage structured note types using Basic Memory's Picoschema system. Schemas define what fields a note type should have, making notes uniform, queryable, and validatable. ## Project scope If the project is unknown, discover it with `bm_project(command="list")`. Pass a nonempty `project` on every note, folder, context and schema call, even with one project or a qualified `memory://` URL. Use the chosen project's name, `workspace/project`, or external ID; `<project>` below is a placeholder for it. Recent activity also requires `project`. Search accepts `project` for one project, `projects` for selected projects, or `all_projects=True` explicitly. Discovery and bundled manuals need no project. Keep the same scope when following returned paths, paginating, or recovering from a refusal. ## When to Use - **New note type emerging** — you notice several notes share the same structure (meetings, people, decisions) - **Validation check** — confirm existing notes conform to their schema - **Schema drift** — detect fields that notes use but the schema doesn't define (or vice versa) - **Schema evolution** — add/remove/change fields as requirements evolve - **On demand** — user asks to create, check, or manage schemas ## Picoschema Syntax Reference Schemas are defined in YAML frontmatter using Picoschema — a compact notation for describing note structure. ### Basic Types ```yaml schema: name: string, person's full name age: integer, age in years score: number, floating-point rating active: boolean, whether currently active ``` Supported types: `string`, `integer`, `number`, `boolean`. ### Optional Fields Append `?` to the field name: ```yaml schema: title: string, required field subtitle?: string, optional field ``` ### Enums Use `(enum)` with a list of allowed values: ```yaml schema: status(enum, current state): [active, blocked, done, abandoned] ``` Optional enum: ```yaml schema: priority?(enum, task priority): [low, medium, high, critical] ``` ### Arrays Use `(array)` for list fields: ```yaml schema: tags(array): string, categorization labels steps?(array): string, ordered steps to complete ``` ### Relations Reference other entity types directly: ```yaml schema: parent_task?: Task, parent task if this is a subtask attendees?(array): Person, people who attended ``` Relations create edges in the knowledge graph, linking notes together. ### Validation Settings ```yaml settings: validation: warn # warn (log issues) or strict (errors) ``` Use `strict` as the canonical enforcing mode. `error` is accepted only as a compatibility alias. ### Complete Example ```yaml --- title: Meeting type: schema entity: Meeting version: 1 schema: topic: string, what was discussed date: string, when it happened (YYYY-MM-DD) attendees?(array): Person, who attended decisions?(array): string, decisions made action_items?(array): string, follow-up tasks status?(enum, meeting state): [scheduled, completed, cancelled] settings: validation: warn --- ``` ## Discovering Unschemaed Notes Look for clusters of notes that share structure but have no schema: 1. **Search by type**: `bm_search(note_types=["meeting"], project="<project>")` — if many notes share a `type` but no `schema/Meeting.md` exists, it's a candidate. 2. **Infer a schema**: Use `bm_schema(command="infer", project="<project>")` to analyze existing notes and generate a suggested schema: ```python bm_schema(command="infer", note_type="Meeting", project="<project>") bm_schema(command="infer", note_type="Meeting", threshold=0.5, project="<project>") # fields in 50%+ of notes ``` The threshold (0.0–1.0) controls how common a field must be to be included. Default is usually fine; lower it to catch rarer fields. 3. **Review the suggestion** — the inferred schema shows field names, types, and frequency. Decide which fields to keep, make optional, or drop. ## Creating a Schema Write the schema note to `schema/<EntityName>`: ```python bm_write( title="Meeting", directory="schema", note_type="schema", metadata={ "entity": "Meeting", "version": 1, "schema": { "topic": "string, what was discussed", "date": "string, when it happened", "attendees?(array)": "Person, who attended", "decisions?(array)": "string, decisions made" }, "settings": {"validation": "warn"} }, content="""# Meeting Schema for meeting notes. ## Observations - [convention] Meeting notes live in memory/meetings/ or as daily entries - [convention] Always include date and topic - [convention] Action items should become tasks when complex""", project="<project>", ) ``` ### Key Principles - **Schema notes live in `schema/`** — one note per entity type - **`note_type="schema"`** marks it as a schema definition - **`entity: Meeting`** in metadata names the type it applies to - **`version: 1`** in metadata — increment when making breaking changes - **`settings.validation: warn`** is recommended to start — it logs issues without blocking writes ## Validating Notes Check how well existing notes conform to their schema: ```python # Validate all notes of a type bm_schema(command="validate", note_type="Meeting", project="<project>") # Validate a single note bm_schema(command="validate", identifier="meetings/2026-02-10-standup", project="<project>") ``` **Important:** `bm_schema(command="validate", project="<project>")` checks for schema fields as **observation categories** in the note body — e.g., a `status` field expects `- [status] active` as an observation. Fields stored only in frontmatter metadata won't satisfy validation. To pass cleanly, include schema fields as both frontmatter values (for metadata search) and observations (for schema validation). Validation reports **missing required fields** (as observation categories, or relations for entity-reference fields) and **invalid enum values**. Undeclared observation categories and relations are listed as informational "unmatched" items. Scalar values are not type-checked. ### Handling Validation Results - **`warn` mode**: Review warnings periodically. Fix notes that are clearly wrong; add optional fields to the schema for legitimate new patterns. - **`strict` mode**: Use where conformance matters (e.g., automated pipelines consuming notes). ## Detecting Drift Over time, notes evolve and schemas lag behind. Use `bm_schema(command="diff", project="<project>")` to find divergence: ```python bm_schema(command="diff", note_type="Meeting", project="<project>") ``` Diff reports: - **Fields in notes but not in schema** — candidates for adding to the schema (as optional) - **Schema fields rarely used** — consider making optional or removing - **Cardinality changes** — a field that moved between single-value and array ## Schema Evolution When note structure changes: 1. **Run diff** to see current state: `bm_schema(command="diff", note_type="Meeting", project="<project>")` 2. **Update the schema note** via `bm_edit` with the `metadata` parameter. Top-level keys are replaced whole, so pass the complete updated `schema` map along with the new `version`: ```python bm_edit( identifier="schema/Meeting", command="set_metadata", metadata={ "version": 2, "schema": { "topic": "string, what was discussed", "date": "string, when it happened", "attendees?(array)": "Person, who attended", "decisions?(array)": "string, decisions made", "location?": "string, where it happened" } }, project="<project>", ) ``` 3. **Re-validate** to confirm existing notes still pass: `bm_schema(command="validate", note_type="Meeting", project="<project>")` 4. **Fix outliers** — update notes that don't conform to the new schema ### Evolution Guidelines - **Additive changes** (new optional fields) are safe — no version bump needed - **Breaking changes** (new required fields, removed fields, type changes) should bump `version` - **Prefer optional over required** — most fields should be optional to start - **Don't over-constrain** — schemas should describe common structure, not enforce rigid templates - **Schema as documentation** — even if validation is set to `warn`, the schema serves as living documentation for what notes of that type should contain ## Workflow Summary ``` 1. Notice repeated note structure → infer schema (bm_schema(command="infer", project="<project>")) 2. Review + create schema note → write to schema/ (bm_write) 3. Validate existing notes → check conformance (bm_schema(command="validate", project="<project>")) 4. Fix outliers → edit non-conforming notes (bm_edit) 5. Periodically check drift → detect divergence (bm_schema(command="diff", project="<project>")) 6. Evolve schema as needed → update schema note (bm_edit) ```
View on GitHub