Engineering NotesMemory and search
Corrected column meanings, kept as table notes for the next user

The status column STAT_CD in a customer table holds 1, 2, and 9. Nothing in the schema says 9 means cancelled, so when someone asks for the number of active customers, the model counts cancelled customers too and the figure goes into a report. If one person corrects it in a conversation ("9 is cancelled"), that conversation gets the right answer. The next day a different person asks about the same table, and the model gets the same number wrong again, because the correction stayed in that one conversation.
Table notes are a shared record: the model writes such a correction onto the table or column. Every later question from anyone who uses that table carries it. Notes pile up from many people's conversations without anyone's approval, so we attach them only to an exact table and column and load them only as dated hints. This post covers where notes attach, what shape they take when they reach the model, and how wrong notes get cleaned up.
A correction tied to a person or to the analysis drops out of the next question
Table analysis infers a good deal about a column's meaning from value distributions, comments, and join relationships (“DDL doesn't say what a column means, so we read its values first”). Some facts still cannot be read from the data: the business meaning of a code value, which time zone a date column is stored in, which join multiplies rows. A person ends up supplying those facts mid-conversation.
There are two obvious places to put such a correction.
| Where it goes | Upside | Limit |
|---|---|---|
| The speaker's personal memory (“Load personal memory on every turn, and rewrite it whole”) | Easy to write, clear ownership | Loaded only in that person's conversations, so the next person makes the same correction from scratch |
| Editing the column description the analysis produced | Visible right in the table card | Re-running the analysis regenerates the description, and the correction goes with it |
That 9 means cancelled is a fact about the table more than about whoever said it, and it stays true however many times the analysis runs. So notes attach to tables and columns but are stored apart from the analysis results, and the model gets them attached when it opens a card. Business definitions the organization has approved live in the glossary (“Revenue differs by team, so questions carry the approved definition”). Notes are the field record that is used straight from conversation, without approval.
Notes attach only to a table identified down to its schema
A note attaches to a database connection, schema, and table, and can name one column. Without a column, it is a note about the whole table. Each note stores who left it and the conversation it came from, so you can later trace its origin.
If the model passes a table name without a schema, the note-recording tool looks for that name among the analyzed tables and fills in the schema. If nothing matches, or the same name exists in several schemas, it does not save and sends the model back to name the table as schema.table. Cards look notes up by exact schema, so a note saved with an empty schema would never show up on any card. Ignoring the schema in the other direction would mix notes for sales.CUSTOMER into the archive.CUSTOMER card.
Columns follow the same rule. A column is attached only when the model names it as an argument; the tool does not infer one from the note text or the preceding SQL. Inference would save the model from typing a column name, but a wrong guess files the note under the wrong column, and that error is hard to spot.
Permission to leave, edit, or delete a note follows permission to read the table. The check is the same one used to open its table card, so you cannot leave a note on a table you cannot see. Notes shown in search results are likewise limited to tables the user's role allows.
Notes survive re-analysis
Because notes are stored apart from the analysis, re-running the table analysis any number of times leaves them untouched. The card is built from the analysis results; notes are read separately and attached each time the card opens.
A renamed column does not lose its notes either. A column note goes under that column's entry only when the name matches the card exactly. If the card has no column by that name, the note moves to the table-level notes field. A note visible at table level, where the model can fix it, beats a note that shows up nowhere.
The same holds when a table disappears from the source database. A table missing from the connection account's table list is only marked Unavailable; its data, notes included, is not deleted (“Schema analysis goes stale, so only changed tables get reanalyzed”). Deletion happens only when an administrator confirms a cleanup, and the confirmation dialog shows how many notes will go with it. Analysis results come back with another analysis run. Notes are what people said in conversation, and nothing can regenerate them.
Notes reach the model three ways, as dated hints
Notes reach the model through three paths.
| Path | Notes loaded | Where they go |
|---|---|---|
| Opening a table card | Up to 20 active notes, most recently updated first | Column notes under that column's entry; the rest in the table-level notes field |
| Table search results | Up to five table-level notes per result table | Each result's notes field |
| Note search inside table search | Notes the question matches | The table appears in results, marked as found through a note |
The third path means a question using words that appear only in a note, not in the card, still puts that table on the candidate list (“Wrong-table SQL still runs, so search narrows the candidates first”).
All three paths trim a note to the same three-field shape: ID, content, and date. The model uses the ID to point at a note it wants to edit or delete.
The date is there to show how old a note is. Observed in production, more than half of active notes contained a point-in-time phrase like "as of 2025-10" or an absolute date. Without a date, the model cannot tell a ten-day-old aggregate from yesterday's. The date sent is the last update. The creation date would make a just-edited note look old and would not match the most-recently-updated sort order. The date is cut in the user's time zone. The model reads "today" and "yesterday" in that zone, so a UTC date would make a note edited in Seoul before 9 a.m. read as the previous day's.
The tool description defines notes as hints to verify, not ground truth. Even when a note says "9 is cancelled," the model can check the value distribution or a code table, and if what it finds differs, it points at the note by ID and edits it.
In one place the system prompt uses notes as direct evidence. You cannot tell which time zone a database stores timestamps in by looking at the values. If a table note or the database description says "timestamps in this database are stored in UTC," the model converts the time zone in the query so that "today" means the user's today. If nothing says so, it assumes the values are already in the user's zone and says in the answer that it assumed this. One line in a note can shift the cutoff for "today's revenue" by nine hours.
Duplicate notes merge, and a table holds up to 40
A note is active, archived, or deleted, and only active notes are sent to the model.
When several people repeat the same correction, the same note piles up. So recording checks for an active note with effectively the same content on the same table and column. Leading and trailing whitespace is trimmed, runs of whitespace collapse to one, and case is folded before comparison; on a match, only the existing note's updated time moves. Identical text attached to a different column is a different note.
A single table holds up to 40 active notes. When a 41st arrives, the note that has gone longest without an update moves to archived, and the model gets a warning saying so. Archived notes are not deleted, but they are no longer sent. Recording the same sentence again moves that note's updated time, so facts that keep coming up across conversations stay longest.
Wrong notes have two ways out.
- The model names a note ID and edits or deletes it. An edit also rebuilds the search embedding. If the rebuild fails, the old vector is cleared, because keeping it would let searches match on the wrong content from before the edit.
- An administrator views and deletes notes in the Memory tab of the table detail panel on the database screen. The audit log records who deleted which note, and a deleted note drops out of the next answer for everyone who uses the table.
Without the administrator path, a bad shared note would stay until the model happened to delete it in someone's conversation. The audit log keeps only the note's identifier, not its content.
The tool description decides what to record, and only chat can write
The model decides when to leave a note. A keyword rule like "save when someone says 'no, 9 is …'" would be predictable, but people phrase corrections in endless ways and no rule keeps up. Instead, the note-recording tool's description sets the conditions for a note worth keeping.
- A long-lived fact such as a column's meaning or value range, a join hint, or a data caveat
- A self-contained sentence that makes sense to someone reading it for the first time months later (nothing tied to the course of this conversation or to a specific moment)
- Attached to the column when the fact is about one column
Records about people do not go into notes. Names, employee or account IDs, email addresses, who did what when, rankings and per-person counts are information about the people inside the data. Notes are loaded for everyone who uses the table, so such content would show up in other users' answers. If a column identifies people, the note records what that column identifies and how it joins to the user directory. Edits carry the same conditions.
The three tools that leave, edit, and delete notes are available only in chat. They are not offered to playbook nodes, which run unattended and repeatedly. A run nobody is watching must not change shared knowledge, and retries must not repeat the same write. Playbooks still read notes.
In runs that must use identical conditions every time, such as accuracy evaluation, note injection and note search are both turned off. Notes change which tables appear in search results, so turning off injection while leaving note search on would still change the results for the same question.
Design choices
Notes are used straight from conversation, without approval. The person who made the correction does not wait for an administrator to register it, and the next person does not hit the same mistake. The cost is that a wrong note spreads as fast. We absorb that risk by loading notes only as hints, keeping the date and source conversation with each one, and giving both the model and administrators a way to delete them. Definitions that must hold as the answer belong in the glossary, which goes through approval.
Duplicates are detected by string normalization only. Merging notes with similar meanings through embeddings would keep the count down, but a slightly different fact would vanish, as with "9 is cancelled" versus "9 is cancellation request received." So only notes with the same wording merge, and we accept that similar notes can sit side by side.
The cap is 40 per table, and past it the note that has gone longest without an update is archived. Facts nobody has recorded again in a long time get pushed out; in return, the number of active notes piling up on one table stays bounded. A card loads the 20 most recently updated among them. If a pushed-out fact still matters, the model can see the warning and record it again.
A note's place is set only by the table and column the model names, and an ambiguous one is not saved. Sometimes that costs the model one more call, but no note ends up invisible on every card or mixed into another schema's card.
If several departments query the same database and the meaning of code values or the storage time zone lives only in someone's head, this structure carries over as is: attach notes to tables apart from the analysis results, load them as dated hints, and give people a direct way to delete them.
What problem does this solve?
More in Memory and search

Engineering Notes · Memory and search
Load personal memory on every turn, and rewrite it whole
A user says, "My account in the issue tracker is this ID.

Engineering Notes · Memory and search
Korean particles break full-text search, so we join words with OR
A table note says 「반품 주문은 ORDRTN 테이블에 따로 쌓인다」 ("returned orders pile up separately in the ORDRTN table"), and…

Engineering Notes · Memory and search
One system prompt edit zeroes cache reads, so changing blocks go last
Every time an agent calls the model, the request carries the tool definitions, the system prompt, and the conv…
