Skip to main content
Glama

memory_stats

Monitor memory store health: track growth, dormant memories, pinned character costs, stale claims, and orphaned graph nodes with per-namespace breakdowns.

Instructions

Return health statistics for the memory store. Use to monitor memory growth, identify dormant memories, and get a per-namespace breakdown of counts and confidence distribution. Call at session start alongside memory_context to assess the state of the knowledge base.

namespace accepts a single name, a comma-separated list (e.g. "crow,my-project"), or omitted for global. A single name and the unscoped call keep the shape they always had: {"ok": true, "flagged_stale": 0, "stats": {...}}. A comma list instead returns the namespace-independent block (namespaces, access_log_rows, query_log_rows, credentials) exactly once under global, plus each namespace's own scoped stats under by_namespace - the session-start protocol's two-call pattern (memory_stats(namespace="crow") then one per project) collapsed into one call that computes the shared block once instead of once per namespace: {"ok": true, "flagged_stale": 0, "namespaces": [...], "global": {...}, "by_namespace": {"crow": {...}, "<project>": {...}}}. Names are de-duplicated, order-preserving; an unknown name fails the whole call and names it, same as memory_recall/memory_search. review_limit applies to every namespace's block.

stats.dormant_count reports memories untouched for 90+ days — a resting signal only, never a confidence change. Dormant memories wake automatically on recall via spreading activation. Memory is never auto-forgotten.

stats.size is the character cost the counts do not show: total_chars, mean_chars, pinned_chars and largest_pinned_chars. pinned_chars is the one to watch — pins load unconditionally at every session start, ahead of and exempt from ranking, so it is the only part of the store paid for on every call regardless of relevance. largest_pinned_chars is the skew check: a tier is not described by how many pins it holds, and when one pin approaches the tier total, the tier IS that pin. Adding well-chosen pins will not fix that; splitting the outlier will. Enumerate the tier with memory_search(pinned=True).

review_limit raises the review.sample, claims.sample and graph.orphan_sample caps (default 5, max 100) so a reconciliation sweep can enumerate every flagged memory — pair with memory_search's ids parameter to pull the full bodies.

stats.graph.orphan_sample names the memories behind graph.orphans: those no relation touches, which spreading activation can never reach. Ordered by confidence, then access count, then recency, so the orphans costing the most retrieval come first, each row carrying its namespace. memory_search(orphans=True) pulls the same set with full bodies; memory_relate reconnects one — where a directional fact genuinely exists.

stats.claims is the state-claim backlog: memories still asserting a PR/MR is open. claims.sample enumerates them, contradicted first, each row tagged contradicted (a later memory in the same namespace already recorded that ref as resolved). open counts every unresolved claim while open_actionable — what the sample lists — excludes claims on deprecated memories. memory_search(claims="open") pulls the same set with full bodies; memory_update(resolve_claims=...) closes them without editing prose.

claims.unverified counts refs a memory names without ever saying what became of them. It is reported for visibility, not action: those refs assert nothing, so they are excluded from open and from sample on purpose. Read them with memory_search(claims="unverified").

flag_stale is deprecated and ignored — auto-demotion to stale contradicted the never-forget model and has been removed. Retained so existing callers do not error.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
namespaceNo
flag_staleNo
review_limitNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv0.13.0
    • addedInput schema / properties / review_limit
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "title": "Review Limit"
      +}
  2. First observedv0.3.1

TDQS

A4.9/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and discharges it: it documents return shapes, that dormant memories are never auto-forgotten and wake on recall, that pins load unconditionally at every session start, that an unknown namespace fails the whole call, and that flag_stale is deprecated and ignored rather than erroring. This is rich behavioral context beyond any structured field.

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 usage, and each paragraph is dense with earning content. However, it is very long (~500 words) and repeats the JSON return shapes for single vs. comma-list namespaces, which adds redundancy; some of that detail could be trimmed without loss.

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

Completeness5/5

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

For a complex tool with no output schema and no annotations, the description covers return structure, per-namespace behavior, error mode, deprecation, and hand-offs to sibling tools. Nothing an agent needs to call it correctly is missing.

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

Parameters5/5

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

Schema coverage is 0%, so the description must compensate and does: namespace accepts a single name, a comma-separated list, or omission (with distinct return shapes for each), review_limit raises sample caps (default 5, max 100), and flag_stale is deprecated and ignored. Every parameter is fully explained with semantics and edge cases.

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 specific verb and resource ('Return health statistics for the memory store') and immediately scopes the purpose: monitor growth, identify dormant memories, per-namespace counts and confidence. An agent can distinguish this from siblings like memory_search or memory_context without opening a 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?

Explicitly says when to call it ('at session start alongside memory_context') and routes to alternatives for follow-up actions: memory_search(pinned=True), memory_search(orphans=True), memory_relate to reconnect, memory_update(resolve_claims=...) to close claims. When/when-not guidance is unusually thorough.

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