Skip to main content
Glama

memory_write

Destructive

Persist and manage long-term memories: write, import files, capture missed sessions, rebuild indexes, and promote or archive memories in the markdown corpus.

Instructions

Writes for the persistent memory corpus — the companion to the read-only memory tool. import (bring files in; CREATES new memories and never overwrites an existing one), capture (write this session's exchanges to the staging store — use when the memory connector was OFF while the work happened and you have realised it mattered; sinceMinutes limits it to the last N minutes and is measured against each exchange's last activity, re-running is safe, and a run that only rewrote the still-open turn with its newer text reports exchangesRefreshed rather than exchangesCaptured), index (rebuild), demote/promote (move a memory between tiers by rewriting ONE frontmatter field). There is no delete action. MEMORY_CURATED_READ_ONLY=1 refuses every write to the memory folder outright. Reads — search, latest, get, neighbors, thread, verify, sessions, index_status, probe_status — are on memory. USE import TO BRING IN SOMEONE ELSE'S MEMORIES — give it an ABSOLUTE path to a file or folder and it reads md/txt/rtf/doc/docx/odt/html/pdf/csv/json/zip, including a ChatGPT export. It never overwrites, so re-running is safe; it REFUSES any item containing a credential and names it; and dry:true reports without writing. Afterwards it tells you what KIND of corpus it derived, because the query advice depends on that. THE LIBRARY: import REFERENCE material (books, manuals, policies) that is big (>200KB) or book-shaped (PDF) WITH category:'' — the directory is created for you, and an import without it is refused, naming the fix. Structure is recovered at import: PDF pages become ## p.N anchors (cite them — a human can open the page), document headings become real sections, CHAPTER lines are promoted. replace:true supersedes a re-issued document (old version to /archive/, stamped, never deleted). Rebuild one with index scope:""; a search never rebuilds a library index inline — a memory search never does. INDEXING IS ASYNC: index returns a jobId immediately and builds off the request (a blocking index used to TIME OUT through MCP); poll index_status on the memory tool with that jobId. One build per index file at a time, so a second concurrent index for the same scope reports that it is already running. demote/promote move a memory between the hot and archive tiers by setting metadata.tier — content is never deleted or moved; archived memories stay searchable, they just lose the boost.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
dryNoimport: report exactly what WOULD be imported and write nothing.
runNoprobe_status: execute the sweep now instead of reading the last sidecar. Probes never run on the search path.
backNothread: how many exchanges BEFORE the anchor to return (default 0).
nameNoget/neighbors/demote/promote: the memory name (filename without .md).
nearNosearch: SOFT time anchor (ISO). Tilts ranking toward that period without hiding anything outside it.
pathNoimport: ABSOLUTE path to a file or folder of memories to bring in. Reads md/txt/rtf/doc/docx/odt/html/pdf/csv/json/zip; a ChatGPT export (conversations.json or its .zip) is recognised and its conversation tree walked in order.
textNoverify: raw text to scan for commit SHAs, instead of naming a memory.
waitNoindex: block until the build finishes instead of returning a jobId. Only for callers that can wait minutes — the default is async because a blocking index TIMED OUT through MCP.
afterNosearch: HARD lower bound on a memory's date (ISO). Excludes — use only when you mean exclusion.
briefNoget: return only the text and where it came from (name, path, body, and what was truncated) — not the ~25 provenance and freshness fields. Use it when you already decided to read this memory and just want the content, e.g. following an absence note that told you to open bestWeak[0]. search/latest: return only name/corpus/score/snippet/provenance and the timestamp per ROW — no path, type, description, per-leg scores, thread position or verified commits. The ENVELOPE is unchanged: indexStale, staleWarning, recencyVoid, recentUnindexed, uncapturedSessions, captureHealth, configWarning and guidance are all still returned, because brief trims rows and never caveats. Use it for a wide scope:'all' sweep where you intend to open one or two results with `get` afterwards.
forceNoindex: ignore the incremental cache and re-embed every file.
jobIdNoindex_status: the job id returned by index.
limitNosearch: max results (default 8). latest: default 5, or 10 in browse mode (no query). sessions: how many conversations (default 20).
queryNosearch: the natural-language query. latest: the terms to filter by — OMIT IT for a browse of the newest documents in the scope.
scopeNosearch/latest: which corpus or corpora — a name, or an ARRAY mixing names freely. Work corpora: 'curated' (default) = hand-written memories from THIS project's memory folder; 'projects' = hand-written memories from OTHER projects' memory folders (same kind of content, hot tier, writable — reached by default via scope-widening whenever another project has memories); 'staging' = auto-ingested conversation exchanges; 'handoff' = institutional HANDOFF/PHASE documents, indexed read-only from outside the memory folders (use this for 'what was the state of X when it was handed over'). 'all' = the WORK corpora only, returned as SEPARATE sections — ranked sections under .groups for search, and for latest one time-ordered section PER CORPUS under .sections, each declaring its own `orderedBy`, because curated files carry no timestamp and their mtime order is bookkeeping, not chronology. LIBRARY categories (imported reference material — books, manuals, policies — each a directory under memory-library/) are searched ONLY when named ('books', ['all','books']) or via 'everything' (= work + every category); they never enter 'all' or the automatic routing, by design, so imported content can never dilute work retrieval. Unknown names error and list what exists. Each corpus has its OWN index and its own statistics — never blended, because blending measurably costs recall. Omit to let phrasing choose (reported in scopeHint). On the `index` action this selects which index to rebuild; the default there is curated + projects + handoff (staging is ingest-driven and expensive; library categories rebuild when named or via 'everything').
actionYesWhich write operation to perform. These change your memories or their derived state; reads live on the `memory` tool.
beforeNosearch: HARD upper bound on a memory's date (ISO). Excludes.
domainNoOPTIONAL, and worth passing when you know: what KIND of work these memories are about. Counting can only separate code from not-code — a novel, a business plan and a day-planner are statistically identical — so this is the only way to get writing/business/research/planning advice apart. Trusted when given; derived from the corpus when not.
offsetNoget: start the body at this character offset, to continue a previous slice.
accountNosearch: restrict to memories written by an account. 'mine' means this surface's own MEMORY_ACCOUNT. Pass an array to read across several. Memories with no account label are ALWAYS returned, so nothing written before labelling existed disappears.
forwardNothread: how many exchanges AFTER the anchor to return (default 8). Named forward, not after, because `after` is search's DATE filter.
outlineNoget: return ONLY the heading outline with sizes and offsets, no body. The cheapest way to navigate a large memory before reading any of it.
projectNosearch: restrict to memories from a project folder. 'this' means the server's canonical project. Memories with no project are always returned.
replaceNoimport (with category): a re-import of the SAME name supersedes the old version — the old file moves to <category>/archive/ stamped metadata.supersededAt (out of the index, never deleted), and the new one takes its place. For re-issued policies/statutes. Without it, an existing name is skipped, as always.
sectionNoget: return only this heading's block (to the next heading of the same or higher level). THE primary read path for a large memory — prefer it over paging.
categoryNoimport: which LIBRARY category to file this under (e.g. 'books', 'manuals', 'policy', 'legal' — any name; the directory memory-library/<category>/ is created if new). REQUIRED for anything big (>200KB of text) or book-shaped (PDF): without it such an import is refused rather than silently diluting the curated corpus. Category content is read-only reference material, indexed separately, and searched only when named or via scope:'everything'. Structure is recovered on the way in: PDF page breaks become '## p.N' anchors, docx/html headings become real markdown headings, plain-text CHAPTER lines are promoted — so the section splitter chapters the document and citations carry page anchors.
keyFactsNoimport: OPTIONAL 1-3 short atomic facts per SECTION of the document being imported, keyed by section name ('<doc>#<section-slug>', or just the section slug for a single-document import). Written from the section's own text, they are indexed as a high-weight keys field so a section can be found by what it IS about rather than only by the words it happens to contain. They never become content: the body, the snippets and the returned text are unchanged. Stored in a sidecar <file>.keyfacts.json. Read only when MEMORY_KEY_FACTS is on.
maxCharsNoget: cap the body (default 20000). A capped response always carries totalChars + truncated so a slice is never mistaken for the whole document. search with scope:'everything': raises that compact view's snippet budget (its default is deliberately small; this is the override).
sessionIdNosearch/latest/sessions: restrict to one conversation (the transcript session id stamped on ingested exchanges).
sinceMinutesNocapture: remember only the last N minutes of this session. Omit for the whole session. The window is measured against each exchange's LAST ACTIVITY, not the moment its question was asked, so a long turn still in progress stays inside a short window. Use when the memory connector was OFF while the work happened and you have realised afterwards that it mattered — the transcript is on disk regardless, so nothing was lost. Captured exchanges go to the STAGING corpus at archive tier and never outrank a hand-written memory; re-running is safe because already-captured exchanges are skipped: a re-run that finds the current turn has grown reports exchangesRefreshed, not exchangesCaptured.
includeSummariesNolatest: context-compaction summary exchanges are DEMOTED by default — still returned, but sorted after ordinary sources, because they restate a whole conversation (matching almost any query) while carrying a recent timestamp for old content. Pass false to exclude them entirely.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Addedv1.7.7

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only say this is a non-read-only, destructive-capable tool, so the description carries the full transparency burden. It discloses no-delete semantics, overwrite behavior only under replace:true, archive moves, credential refusal, dry-run reporting, async index behavior with jobId polling, the MEMORY_CURATED_READ_ONLY guard, and the non-destructive nature of demote/promote. These are materially valuable beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The content is dense and well-organized at a macro level—actions, import, library, indexing, tier moves—but it is presented as a wall of prose with all-caps emphasis and some repetition (e.g., re-running safety appears for both import and capture). It earns most of its space but is not tight or cleanly front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex 31-parameter write tool with no output schema, the description covers the key behaviors, side effects, and result signals: jobId return, exchangesRefreshed vs exchangesCaptured, refusal naming the fix, derived corpus kind, and archive stamps. It could be more explicit about exact response shapes for every action, but the most decision-relevant outcomes are disclosed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 31 parameters thoroughly. The tool description adds action-level context—such as async index behavior and import safety guarantees—but mostly repeats or restates what the schema already says. That fits the high-coverage baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens by stating it writes to the persistent memory corpus and positions itself as the companion to the read-only `memory` tool. It then enumerates the specific write actions (import, capture, index, demote/promote) and explicitly routes reads to the sibling tool, making its scope unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives concrete when-to-use guidance: reads live on `memory`, writes belong here; import is for bringing in external memories, capture is for backfilling sessions when the connector was off, index is for rebuilding, and demote/promote adjusts tiers. It also states exclusions, such as 'There is no delete action' and when a write is refused.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Deploy Server

Other Tools