---
title: "Observations and relations"
description: "How Basic Memory turns your notes into searchable facts and a connected knowledge graph — and why you rarely need to write the syntax yourself."
canonical_url: "https://docs.basicmemory.com/concepts/observations-and-relations"
---
# Observations and relations

> How Basic Memory turns your notes into searchable facts and a connected knowledge graph — and why you rarely need to write the syntax yourself.

Basic Memory notes aren't just text. Each note can contain **observations** (individual facts) and **relations** (links to other notes). Together, they turn a folder of Markdown files into a searchable, navigable knowledge graph.

The important thing to know up front: **you don't need to write these by hand.** When you ask your AI assistant to write a note, it creates observations and relations automatically. You should understand what they are so you can read your notes and give feedback, but you never need to memorize the syntax.

## Observations

An observation is a single fact, captured as a list item with a category in brackets:

```markdown
- [decision] Use Postgres for primary storage #database
- [risk] Latency spikes under heavy load #performance
- [preference] Dark mode for all internal tools #ux
```

The category (the word in brackets) classifies the kind of fact. The rest of the line is the content. There is no fixed list of categories — use whatever makes sense for what you're capturing:

```markdown
- [tool] Basic Memory uses SQLite for local indexing
- [recipe] Bloom the espresso for 30 seconds before extraction
- [symptom] App crashes on launch after upgrading to iOS 18
- [quote] "Simplicity is the ultimate sophistication" — Leonardo da Vinci
- [milestone] v1.0 shipped on March 15
```

Categories help your AI assistant understand what kind of information it's looking at. When it builds context from your knowledge base, it can distinguish a decision from a risk, a preference from a requirement. That distinction matters when it's helping you reason through a problem.

### Avoid checkbox and timestamp markers

Observation categories are semantic labels, not task state or transcript time. Basic Memory does not index these Markdown checkbox markers as categories:

```markdown
- [ ] Not started
- [x] Complete
- [X] Complete
- [-] Canceled
- [/] In progress
- [>] Deferred
- [?] Needs clarification
```

Timestamp-shaped prefixes on transcript lines are also ignored as categories. Use a descriptive label such as `[decision]`, `[status]`, or `[follow-up]` when you want the line indexed as an observation.

That includes both a single clock value and a spaced range:

```markdown
[24:33.098] Speaker: We should keep the existing API.
[24:33.098 - 24:41.260] Speaker: The migration can happen later.
```

Only clock-shaped transcript markers are excluded. A descriptive category that happens to contain time-like text is still treated as a category.

### Tags within observations

The `#hashtags` at the end of an observation line add extra searchability:

```markdown
- [decision] Switch to async job processing #architecture #backend
- [feedback] Users want faster search results #ux #search
```

Tags are indexed and searchable with the `tag:` prefix in search queries. They cut across categories — you might tag observations from many different notes with `#database` and then find all of them in one search.

Tags are optional. Many observations work fine without them. Add them when you want a cross-cutting way to find information later.

### When a fact holds (valid time)

Some facts are only true for a while: a decision that took effect on a date, a policy that ran until a cutover, a deadline. As of [v0.24](https://docs.basicmemory.com/whats-new/v0-24), an observation can say when it holds with a qualifier placed right after the category:

```markdown
- [decision] @effective:2026-06-10 The cache layer will use Redis.
- [decision] @effective[2026-06-10,2026-07-27) Redis served cache traffic until the cutover.
- [incident] @occurred:"June 10, 2026" The primary database failed over.
- [deadline] @due:2026-09-30 Ship the migration tooling.
- [status] @2026-07 Search rewrite in beta.
```

The qualifier is indexed as **valid time** — when the note *says* something was true — which is separate from when the note was written or edited.

- **Kinds:** `effective`, `valid`, `occurred`, `due`, and `mentioned`. The kind is optional; a qualifier without one (`@2026-07`) is `valid`.
- **Points:** a date covers the span its precision implies — `@2026` is that year, `@2026-06` that month, and `@2026-06-10` that date onward.
- **Ranges:** use bracket notation, `[` or `]` for an inclusive end and `(` or `)` for an exclusive one, and leave a side empty for an open range: `@effective[2026-06-10,)`. Range bounds are written as `YYYY-MM-DD` dates or timestamps; a timestamp with no offset is read as UTC.
- **Multi-word dates** go in double quotes: `@occurred:"June 10, 2026"`, `@"June 2026"`. An unquoted point is one word.
- **Relative dates aren't accepted.** `@due:tomorrow` or `@occurred:"2 days ago"` would mean something different every time the note is indexed, so write the actual date.

A qualifier that doesn't parse as a date is left alone as ordinary observation text — the line still indexes and searches normally. Basic Memory logs a warning only when you plainly meant a qualifier: an unknown kind (`@asserted:2026-06-10`), an unterminated quote, or an unquoted multi-word date.

Search can then ask what was true at a moment or during a period. See [Searching by valid time](https://docs.basicmemory.com/concepts/metadata-search#searching-by-valid-time).

<note>

Ambiguous slash dates like `@occurred:03/04/2026` are read using the `date_order` setting (`YMD` by default; `DMY` or `MDY` also accepted). ISO dates such as `2026-03-04` are never reinterpreted, so prefer them.

</note>

## Relations

A relation is a link from one note to another, with a label that describes how they're connected:

```markdown
## Relations
- depends_on [[Caching Layer]]
- relates_to [[Latency Budget]]
- owned_by [[Platform Team]]
```

The label before the `[[link]]` is the relation type. Like categories, there is no fixed list — use whatever describes the connection:

```markdown
- implements [[RFC-042 Async Processing]]
- contrasts_with [[Monolith Architecture]]
- learned_from [[Q3 Retrospective]]
- inspired_by [[Obsidian Plugin System]]
- blocked_by [[Auth Migration]]
```

Relations are directional. `System Design - depends_on -> Caching Layer` creates a link in the knowledge graph from one note to the other. Your AI assistant can follow these links to build context — starting from one note and pulling in the connected notes to understand the bigger picture.

<note>

**Quote multi-word relation types.** A relation type is a single token (`depends_on`, `relates_to`). If you want a multi-word type, **quote it** — `"depends on" [[Caching Layer]]`. Unquoted prose before a wikilink is no longer treated as a relation type: a bare or prose list item like `- [[Caching Layer]]` or `- see also [[Caching Layer]]` is indexed as a generic `links_to` connection. (Changed in [v0.21.0](https://github.com/basicmachines-co/basic-memory/releases/tag/v0.21.0).)

</note>

### Force a generic relation from single-word prose

A single token before a wikilink normally looks like an explicit relation type. When that token is prose instead, end the list item with `#bm:links_to`:

```markdown
- Mother [[Alice]] #bm:links_to
```

This creates the generic `links_to` relation instead of a `Mother` relation. The directive stays in the Markdown source so the intent is visible, but Basic Memory removes it from the indexed observation and relation text. This syntax was added in v0.23.1.

### Inline references

You can also link to other notes anywhere in a note's body text using `[[wiki links]]`:

```markdown
We decided to follow the approach from [[API Design Principles]]
because it aligns with our [[Team Standards]].
```

These inline references also create connections in the knowledge graph. The difference is that relations in a list with a leading word have explicit types (`depends_on`, `relates_to`), while inline references create a generic `links_to` connection. Both are useful.

A wikilink written inside inline code or a code block — for example ``[[Example]]`` in documentation about wikilinks — is treated as code and doesn't create a relation.

### Ordinary Markdown links

Since [v0.24](https://docs.basicmemory.com/whats-new/v0-24), standard Markdown links to files in the same project create `links_to` connections too, so notes written in other editors or exported from other tools join the graph without converting their links:

```markdown
Follow [the deploy checklist](../ops/Deploy%20Checklist.md) before release.
```

Paths resolve relative to the linking note (a leading `/` means the project root), and only to that exact file. External URLs, images, fragment-only links, links inside code, and paths outside the project are ignored. Markdown links are always `links_to`; for a typed relation, use the wikilink form. See [Knowledge Format](https://docs.basicmemory.com/concepts/knowledge-format#ordinary-markdown-links) for the full rules.

### When a linked note is deleted

Deleting a note doesn't erase the relations that pointed at it. They go back to the unresolved state a link to a not-yet-written note has, keeping the original link text, so you can still find the dangling references, and recreating the note reconnects them. (Before v0.24, deleting a note silently removed its inbound relations.)

Wikilinks resolve exact permalinks, titles, and paths first. Root-level filename stems receive the same `.md` fallback as nested paths. If exact resolution fails, a unique case-insensitive filename alias can bridge underscore/hyphen differences; aliases that match more than one note stay unresolved. See [Knowledge Format](https://docs.basicmemory.com/concepts/knowledge-format#how-wikilinks-resolve) for examples and write-identity rules.

## Why this matters

Observations and relations aren't just formatting — they're what makes Basic Memory's search and navigation powerful.

### Precise search

Every observation is indexed individually. When you search your knowledge base, Basic Memory doesn't just match against whole documents — it can surface a specific fact from deep inside a long note.

If you have a 2000-word architecture document with dozens of observations, a search for "database migration strategy" can find the one relevant observation without forcing you to read the entire note. Semantic search matches the meaning of your query against each observation, so even different wording will find the right fact.

### Knowledge graph navigation

Relations create a graph you can traverse. The `bm_context` tool follows links between notes to assemble relevant information from across your knowledge base. When you ask your AI assistant about a topic, it doesn't just find one note — it follows relations to pull in connected context.

For example, if you ask about a system design decision, the assistant might start with the design note, follow a `depends_on` link to the caching strategy, then follow a `relates_to` link to the performance requirements. That chain of connections gives it a much richer understanding than any single note would.

### AI context building

Categories, tags, and relation types give your AI assistant structured metadata to work with. It can filter observations by category, search by tag, and navigate by relation type. This structure means the assistant can be selective about what context it pulls in, rather than dumping entire documents into the conversation.

## Enforcing structure with schemas

If you want to ensure consistency across similar notes, Basic Memory's schema system (introduced in v0.19) can validate that notes of a certain type contain the observations and relations you expect.

For example, you could define a schema that requires every "person" note to have a `name` observation and a `works_at` relation. You can then validate notes on demand — ask your AI to check them (the `bm_schema(command="validate")` tool) or run `bm schema validate` — and the report flags anything that's missing. Validation warns rather than blocking writes.

<note>

See [Schema System](https://docs.basicmemory.com/concepts/schema-system) for details on defining and applying schemas.

</note>

## Teaching your AI with skills

The `memory-notes` skill teaches your AI assistant best practices for writing observations and relations — what categories to use, how to structure relations, and when to add tags. Skills are a way to encode your preferences so the AI writes notes the way you want without being reminded every time.

<note>

See [Agent Skills](https://docs.basicmemory.com/integrations/skills) for details on how skills work.

</note>

## Next steps

<card-group>
<card icon="i-lucide-search" title="Semantic Search" to="https://docs.basicmemory.com/concepts/semantic-search">

Learn how observations power precise semantic search across your knowledge base.

</card>

<card icon="i-lucide-shield-check" title="Schema System" to="https://docs.basicmemory.com/concepts/schema-system">

Validate and enforce structure on your notes with schemas.

</card>

<card icon="i-lucide-at-sign" title="Memory URLs" to="https://docs.basicmemory.com/concepts/memory-urls">

See how links resolve and navigate knowledge.

</card>

<card icon="i-lucide-file-text" title="Knowledge Format" to="https://docs.basicmemory.com/concepts/knowledge-format">

Learn the base note format that observations and relations build on.

</card>
</card-group>


## Sitemap

See the full [sitemap](https://docs.basicmemory.com/sitemap.md) for all pages.
