Skip to content

Memory

Copy page

Memory is the persistence layer that holds typed records across sessions, projects, and agents. Every other component depends on it.

An MCP server (HTTP transport) at https://your-memory-host.example.com/mcp/memory/ exposing six tools:

ToolPurpose
memory_readRead a named record
memory_writeCreate or update a record with typed metadata
memory_recallTag-filtered batch read (used by SessionStart auto-recall)
memory_searchFull-text + tag search
memory_listList record names by tag
memory_deleteRemove a record

Records are typed (feedback, project, user, reference, etc.), tagged with project scope (["my-app"], ["tapestry"], ["example-project"]), attributed to an actor (claude-code, the operator, the Observer), and chained via provenance links.

Lives at services/agent-context/ (Render service memory-mcp).

Without persistent memory, every session starts cold. Operators have to re-explain context; agents make the same mistakes; corrections evaporate. The cost is paid every conversation.

Memory turns those costs into one-time learnings. A correction saved once becomes guidance forever after. A project’s accumulated context auto-recalls at SessionStart. The Observer’s synthesis memos compound over time.

Memory is the substrate of the shared multi-agent memory model — hierarchical scopes, provenance chains, visibility tiers, reinforcement model.

flowchart TB
    P[Plugin hooks<br/>SessionStart auto-recall<br/>friction-as-memory writes]
    O[Observer<br/>writes synthesis memos]
    OP[Operator<br/>feedback + decisions]
    M[Memory MCP<br/>memory-mcp]
    PG[(Postgres<br/>postgres)]
    OBSY[Observatory<br/>memory lens]
    P -->|write| M
    O -->|write| M
    OP -->|write via memory_write tool| M
    M --> PG
    M -->|read| OBSY

The Memory MCP is read-write to plugins (auto-recall at SessionStart, friction writes mid-session), the Observer (synthesis memos), and operators (typed records via memory_write). It backs onto Postgres (postgres on Render). The Observatory reads through it for the memory lens.

Consuming the existing deployment (default): add loom-memory to your project’s .mcp.json:

{
"mcpServers": {
"loom-memory": {
"transport": {
"type": "http",
"url": "https://your-memory-host.example.com/mcp/memory/"
}
}
}
}

That’s it. tapestry onboard writes this block for you. Each operator gets a fallback tenant — no JWT needed (v0.1.8 wired self-host fallback per services/agent-context/mcp_self_host_middleware.py).

Self-hosting Memory:

  1. Copy services/agent-context/ into your Tapestry deployment.
  2. Provision a Render Postgres instance for record storage.
  3. Deploy as a Render Web Service from render.yaml (search memory-mcp).
  4. Required env vars:
    • DATABASE_URL — Render Postgres connection string
    • PLATFORM_MODE=hosted (multi-tenant) or =self_host (single-tenant, default)
    • JWT verification keys (only for hosted mode)
  5. Point your .mcp.json at your deployment’s URL.

See Platform dependencies for the full Render setup.

  • MCP server is reachable: call memory_list with a known tag. Non-error response = reachable.
  • SessionStart auto-recall works: start a new Claude Code session in a project with prior memories. The session header should include an auto-recall block listing past memories tagged for the project.
  • Writes persist: call memory_write for a test record, then memory_read it. The record should round-trip with metadata intact.
  • Tag scoping works: write a record with project_tags=["test-scope"], then memory_recall with that tag — only that record returns.
SymptomLikely causeWhere to look
MCP UNREACHABLE: HTTP 404 in SessionStart hookRender cold-start (service spinning up)Wait 30-60s; restart Claude Code; if persistent, check Render dashboard for service health
memory_write returns success but record absent on memory_readTag mismatch; you wrote to one tag but recalled with anotherCheck project_tags on the write call matches the tags filter on the read call
memory_write returns 4xx with WAF blockRender WAF blocking content that looks like Python (try/except/import patterns)Simplify the memo content; see feedback_render_waf_blocks_python_looking_memory_writes
Auto-recall block empty in SessionStartNo records tagged for current projectVerify LOOM_PROJECT_ID in .env matches a tag you’ve written records with
MCP tools missing from Claude Code.mcp.json malformed or not loadedRestart Claude Code; check JSON syntax; verify transport.url is reachable from your machine
[loom-memory · MCP UNREACHABLE: HTTP 404] on localhostHook check is misconfigured for localhost; the actual hosted endpoint worksConfirm by calling memory_list directly — if it succeeds, the localhost check is stale and not load-bearing