Skip to main content
Glama
ClickHouse Loom

ClickHouse Loom

Official

loom_memory_apply

Preview and apply one change to many existing memories by keys, filter, or search—delete, expire, lock, label, or demote—with dry-run defaults. Never creates memories.

Instructions

WHAT: One change over many EXISTING memories, previewed first; it never creates one (save facts with loom_memory_set, one per fact). target names exactly one of keys | filter (tags_any/tags_all, memory_type, key_prefix, created_before/after, confidence_lte, source_trace) | search {query}; limit is required for filter/search; action is delete | expire | lock | label | demote with its block (expire {ttl_seconds|until, on_expire}, lock {mode}, label {tags, mode add|replace|remove}, demote {confidence_factor | confidence_delta}); reason is required. dry_run defaults to TRUE and lists every row it would touch (would_apply / refused); call again with dry_run=false to write. A locked row comes back as status 'refused', never an error. WHEN: anything that names a set rather than one key — 'forget everything about the Q3 migration', 'these are getting stale, lower their confidence', 'tag every runbook as ops', 'lock everything I saved about the incident', 'expire the meeting notes in 30 days'. WHEN NOT: One key (memory.delete / memory.set / memory.lock). A whole agent or user (memory.clear, admin, via loom_op); a user's request to delete all their data is erasure.request (via loom_op where it is not listed). Never skip the dry run when the user has not seen the list.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "target": "<target>",
      "action": "<action>",
      "reason": "<reason>"
    },
    "name": "loom_memory_apply"
  }
}

Input Schema

NameRequiredDescriptionDefault
lockNo
labelNo
limitNo
actionYes
demoteNo
expireNo
reasonYes
run_idNo
targetYes
dry_runNo
namespaceNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv1.1.0

TDQS

A4.5/5.0
Behavior4/5

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

Goes well past the annotations: dry_run defaults to TRUE, the preview returns would_apply/refused rows, locked rows surface as status 'refused' rather than errors, and reason is mandatory. It also maps each action to its required parameter block. The remaining tension is that a 'delete' action is advertised while destructiveHint=false, but the dry-run-by-default and refusal semantics largely explain the safe posture, so it does not read as a flat contradiction.

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?

WHAT / WHEN / WHEN NOT headers front-load the purpose and the routing rules, and the compressed clause style packs a lot into a small space. The middle sentence enumerating every action block is dense and reads as a schema restatement, which costs some clarity.

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 an 11-parameter, multi-action bulk mutation with no output schema, the definition covers selection, action blocks, the dry-run contract, refusal behavior, and sibling routing. Gaps are the unscoped run_id/namespace parameters and no indication of what a non-dry-run success response contains.

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

Parameters4/5

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

Schema description coverage is 0%, so the description carries the burden and does so for the critical parts: target must name exactly one of keys|filter|search, limit is required for filter/search, and each action pairs with its own block (expire/lock/label/demote) with reason required. It leaves run_id, namespace, and the interaction of limit with the keys target unexplained, which keeps it short of a 5.

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?

Opens with a precise verb+resource+scope: 'One change over many EXISTING memories, previewed first; it never creates one.' It explicitly rules out the sibling that could be confused with it ('save facts with loom_memory_set, one per fact'), so an agent can distinguish it from loom_memory_set/loom_memory_delete without opening any schema.

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?

Dedicated WHEN and WHEN NOT blocks give concrete trigger utterances ('forget everything about the Q3 migration', 'tag every runbook as ops') and route single-key cases to memory.delete/memory.set/memory.lock, bulk cases to memory.clear/admin via loom_op, and erasure requests to erasure.request. It also adds a procedural guard ('Never skip the dry run when the user has not seen the list').

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