Skip to main content
Glama

memory_write

Destructive

Write to the persistent memory corpus: import files, capture session exchanges, rebuild indexes, and promote or demote memories between tiers. No delete action.

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), 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.

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.3/5.0
Behavior5/5

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

Goes well beyond the annotations: import CREATES and never overwrites an existing memory, demote/promote rewrites exactly ONE frontmatter field, there is no delete action at all, and MEMORY_CURATED_READ_ONLY=1 refuses every write outright. These are exactly the mutation semantics, idempotence, and config-gate facts an agent needs before writing.

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

Conciseness4/5

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

Front-loaded with purpose and the sibling relationship, then the operation list, then the read-only gate. It is dense and long for a description, but every clause (no-delete, read routing, config gate) carries information an agent would otherwise have to discover by erroring.

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 31-parameter write tool with no output schema, the description supplies the mutation semantics, the write-vs-read boundary, and the environment gate; return values are largely the domain of the companion `memory` tool. It does not describe what the write actions return (e.g. jobId, counts), which is the main remaining gap.

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 31 parameters are already documented in structured form and no description-side compensation is required. The description adds action-level meaning that maps onto the `action` enum but contributes no additional parameter syntax or format detail beyond the schema.

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?

Names a specific write surface ('Writes for the persistent memory corpus') and enumerates its operations (import, capture, index, demote/promote) while explicitly positioning itself against the read-only `memory` sibling. An agent can tell instantly what this tool does and does not cover.

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

Usage Guidelines4/5

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

Each action carries a parenthetical telling the agent when it applies (import = bring files in; capture = write this session's exchanges; index = rebuild; demote/promote = move between tiers), and the final sentence routes all reads to `memory`. It stops short of explicit when-not guidance for choosing between import and capture in ambiguous cases.

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