Memory

Notes

Notes are user-authored memories. They live in the same agent_memories table as every other memory entry, tagged with the literal string 'note'. The first line of the text is treated as the title, the rest as the body. The Brain UI surfaces notes as their own list with edit, AI-edit, delete, and share actions.

Updated today

Overview

At a glance
Table
agent_memories
Selector
tags @> '{note}'
Endpoint
/api/brain/notes
Tool
brain_manage_notes in chat-tools.ts
Title rule
First line of text becomes the title in the UI
Share path
Sharable as a public viewer at /s/[slug] with the note resource type

Notes are the place a user puts free-form context they want the model to remember. A market positioning brief, a list of personas, a research summary, a contract template. The platform does not enforce a structure; the user types whatever the model needs to ground on.

Under the hood there is no separate notes table. A note is an agent_memories row with the note tag and a user-facing title rule. Every retrieval path that already reads memories surfaces notes without extra work. Conversely, anything a skill writes can be promoted to a note by toggling the tag.

Data model

The same schema as a memory, with one tag carving notes out.

supabase/migrations/202602080002_agent_memories.sqlsql
1-- A note row, as it appears in agent_memories
2-- (the schema is identical to a memory; the tag is the difference)
3
4id uuid -- generated
5agent text not null -- 'user' for hand-written notes
6text text not null -- title + body, separated by newline
7embedding vector(1536) -- computed at write
8tags text[] not null -- contains 'note'
9metadata jsonb not null -- optional icon, color, source, etc.
10user_id uuid -- owner
11created_at timestamptz not null
Note
The agent field holds the writer's identity. For user-authored notes it is user. For notes generated by a skill that wants to surface itself in the Brain UI, the skill writes its own id and adds the note tag.

API endpoints

One route handles every CRUD action with a discriminated action field.

src/app/api/brain/notes/route.tsts
43// GET /api/brain/notes - list notes for the current user
44const { data } = await supabase
45 .from("agent_memories")
46 .select("id, text, tags, metadata, created_at")
47 .eq("user_id", userId)
48 .contains("tags", ["note"])
49 .order("created_at", { ascending: false })
50
51// First line of text → title, rest → snippet
52return rows.map((r) => {
53 const [first, ...rest] = (r.text ?? "").split("\n")
54 return { id: r.id, title: first, snippet: rest.join("\n"), tags: r.tags }
55})
MethodActionEffect
GETlistReturns notes ordered by created_at desc
POSTcreateInserts a new note. Re-embeds the text. Returns the row.
POSTreadReturns the full text of one note by id
POSTupdateUpdates title and/or body. Re-embeds on text change.
POSTai_editSends the current text plus an instruction to Haiku, replaces text with the response, re-embeds
DELETEdeleteRemoves the row

Notes UI

The Brain page renders notes as a sortable, searchable list.

The Brain page at /dashboard/brain shows notes in a list ordered by most recent. Each row shows the title (first line of text), a one-line snippet (next characters), and the timestamp. Clicking opens a side panel with the full body and the edit affordances. The list updates optimistically on edit and delete.

Search inside the Brain UI runs over note titles and bodies. Behind the search input is a debounced server fetch that filters by case-insensitive substring; semantic search is one click away through the global Ask box.

AI edit

A small Haiku call that rewrites a note in place.

src/app/api/brain/notes/route.tsts
1// POST /api/brain/notes with action=ai_edit
2// Body: { id, instruction }
3
4const note = await loadNote(id, userId)
5const edited = await haikuComplete({
6 system: AI_EDIT_SYSTEM, // 'You are editing a user note...'
7 user: JSON.stringify({ note: note.text, instruction }),
8})
9const embedding = await embedText(edited)
10await supabase.from("agent_memories").update({
11 text: edited,
12 embedding,
13}).eq("id", id).eq("user_id", userId)
Tip
The AI edit action lets the user issue short instructions in plain language: tighten this, translate to Romanian, add bullet points, summarise. The model rewrites the note and the new text is re-embedded so the retrieval paths surface the updated version.

Tags and scoping

Beyond the note tag itself, other tags scope a note to a project, persona, or category.

TagPurpose
noteCarves the row out of agent_memories as a user-facing note
project:<id>Scopes the note to one project workspace
persona:<persona>Marks the note as authored under a specific persona
topic:<slug>Free-form topic tag the user picks (positioning, pricing, etc.)
starredSurfaces the note in the pinned section of the Brain page

File map

src/app/api/brain
notes/route.tslist, create, read, update, ai_edit, delete
src/lib
agentMemory.tsaddMemory, searchMemories, recallMemories
chat-tools.tsbrain_manage_notes tool definition
src/components
share/SharedNoteViewer.tsxpublic viewer for shared notes

Glossary

Note
An agent_memories row tagged with 'note'. User-facing, editable, surfaced as a card in the Brain UI.
Title rule
The convention that the first line of text is treated as the title and the rest as the body. Enforced by the API response shape.
AI edit
A Haiku call that rewrites the note text against a short instruction and re-embeds the result.
Promotion
Turning a regular memory into a note by adding the 'note' tag, or demoting back by removing it.
Brain page
The /dashboard/brain route that lists notes and uploaded files alongside the global Ask box.