anti_pattern
Capture a tempting-but-wrong move, the mechanism that makes it fail, and the concrete alternative, so later agents recognize and avoid repeating the same pitfall.
Instructions
Record a pitfall: a move that looks right, why it fails, and what to do instead.
For a mistake worth not repeating. A fact that simply holds is a note(); how an analysis ran and what it settled is a reasoning(). Stored as type='anti_pattern' and read back under TEMPTATION / WHY WRONG / INSTEAD; pulse() counts the open ones for a domain and must_read(type='anti_pattern') lists them.
ONE pitfall per memory: a second temptation from the same session is its own anti_pattern(), connected with link_memories().
Returns the new uid and the project it landed in, plus similar when
the store already holds something close: correct, drop or link it as
similar_hint says. A field over its ceiling is refused and nothing is
written.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| also | No | other domain paths this belongs to, comma-separated: the subjects that cut across the tree `domain` sits in, such as the end-to-end flow a routine is one step of. Every read scoped to one of them returns it. A path `domain` already sits under is dropped as redundant. At most 200 characters each. | |
| tags | No | comma-separated keywords and synonyms. Retrieval is BM25 over content, tags and domain paths, and tags weigh second only to the body, so they make a memory findable by words its own text never uses: the identifier, the error string, the plain phrasing someone will type. A memory with none is reachable only by quoting itself. At most 1000 characters. | |
| title | Yes | one line naming what this memory is about, in the words someone would look for it by. A list shows it instead of the opening of the body, and it outweighs every other field in search, so a title that repeats the type ("note about the parser") names nothing. At most 120 characters; a name that needs more is summarizing the body. | |
| domain | No | the subject this belongs to, as a path from the outermost scope in ('acme/x100/p200'). File it as deep as the fact is specific -- a note about one routine goes on the routine, and still comes back when someone asks about the module or the product above it. At most 200 characters. | |
| instead | Yes | what to do, concrete enough to act on. | |
| pattern | Yes | the temptation, as the next agent will meet it: the move that looks right at the time. At most 800 characters. | |
| session | No | groups what one conversation writes. Leave it empty to use this server process's own stamp. | |
| why_wrong | Yes | the mechanism that makes it fail, specific enough to recognise the next time. | |
| source_ref | No | what the fact came FROM -- a path, a URL, a table name -- so a later pass can check the claim against the thing itself instead of inferring what to check from the wording. At most 500 characters. | |
| review_after | No | when this stops being safe to trust unchecked, as a date ('2026-11-01') or a span from today ('90d'). pulse() counts what is overdue in a scope as `scope.stale` and optimize_scan lists it. Leave it empty for anything that does not go stale -- most facts do not, and a date nobody meant is worse than none. |