Quickstart — Agentic memory
You'll create a memory project, write your first observation, and query it with recall. Five minutes.
1. Create the memory project
uv run grail init ./my-memory --memory
The difference vs KB: instead of an input/ folder, GRAIL creates memories/. Final structure:
my-memory/
├── grail.yaml
├── meta.json ← project identity (ULID, mode, dates)
├── memories/ ← observations go here, organised by folders
└── output/ ← parquet, FAISS, etc.
The --memory flag flips memory mode in grail.yaml:
mode: memory
2. Write your first observation
From Python (the SDK is the natural path for agents):
import asyncio
from grail import MemoryProject
async def main():
mp = MemoryProject("./my-memory")
reply = await mp.add_observation(
title="Acme picked Postgres over DynamoDB",
content=(
"In Tuesday's architecture review, Acme committed to Postgres "
"for the order-history service because of transactional needs "
"across the inventory and payments tables."
),
category="work/clients/acme",
tags=["decision", "architecture"],
entities=[
{"name": "Acme", "type": "ORGANIZATION", "description": "Client"},
{"name": "Postgres", "type": "TECHNOLOGY", "description": "Chosen DB"},
{"name": "DynamoDB", "type": "TECHNOLOGY", "description": "Rejected alternative"},
],
relationships=[
{"source": "Acme", "target": "Postgres", "relationship_type": "CHOSE",
"description": "for transactional order-history"},
{"source": "Acme", "target": "DynamoDB", "relationship_type": "REJECTED",
"description": "lacks cross-table transactions"},
],
confidence=0.95,
)
print(reply.ok, reply.data["observation_id"])
asyncio.run(main())
What happens under the hood:
- GRAIL writes
memories/work/clients/acme/acme-picked-postgres-over-dynamodb.mdwith YAML frontmatter (title, tags, observed_at, confidence, …). - Entities and relationships are merged directly into parquet — no extraction LLM call.
- The folder
work/clients/acmebecomes a community (folders-as-communities). - If you configured embeddings, entity descriptions are embedded into the vector store.
3. Recall
recall is the memory-only search mode — zero LLM, zero embedding, just a structural filter over the columns:
# Everything for Acme in the last 7 days tagged "decision"
uv run grail query ./my-memory --mode recall \
--since 7d \
--category "work/clients/acme/**" \
--tag decision
Or from Python:
recall = await mp.recall(
mode="recall",
category="work/clients/acme/**",
tags=["decision"],
since="7d",
)
for obs in recall.data["observations"]:
print(obs["observed_at"], obs["title"])
Filters also work as a modifier on any other mode:
# Cascade scoped to recent Acme observations
uv run grail query ./my-memory "Why did Acme rule out DynamoDB?" \
--mode cascade \
--since 30d \
--category "work/clients/acme/**"
4. Consolidate
When memory starts growing (say above 30 entities), run the proposal generator. It doesn't mutate anything — just writes suggestions you review:
uv run grail consolidate ./my-memory
Generates four kinds of proposals:
| Kind | What it proposes |
|---|---|
merge_aliases | "These two entities look like the same person/thing" |
discover_community | "These entities form a new dense community" |
move_entity | "This entity belongs more to another folder" |
split_folder | "This folder has two distinct clusters" |
You review them and apply:
uv run grail proposals list ./my-memory
uv run grail proposals apply ./my-memory --accept <proposal_id>
5. Wire it to your agent
The SDK is enough for agent code. If your agent is Claude Code, Codex, or OpenCode, the skill wires it automatically via tool calls — the agent writes observations declaring what it learns, without writing Python.
Compared to knowledge base
Mode · Knowledge base | Mode · Agentic memory | |
|---|---|---|
| Who writes | An LLM reads documents | Your agent declares entities |
| Write cost | $$ per chunk | $0 (no LLM) |
| Folder structure | Flat input/ | Hierarchical memories/<category>/ |
| Communities | Leiden | Folders + proposals |
recall mode | — | ✓ |
See The two modes for the full picture.
Next step
- Skill quickstart if your agent is Claude Code, Codex, or OpenCode.
- Memory model to understand how
recallworks and when toconsolidate. - Search modes to combine
recallwithcascadeandagent.