Skip to main content
Glama
Cloto-dev

CPersona

Official
by Cloto-dev

store

Idempotent

Store a memory for future recall: put the text in content. agent_id may be omitted on a connection that can write to exactly one agent (the agent used is echoed as resolved_agent_id), and source defaults to that agent.

Instructions

Store a memory for future recall: put the text in content. agent_id may be omitted on a connection that can write to exactly one agent (the agent used is echoed as resolved_agent_id), and source defaults to that agent. lock:true also locks the memory, as lock_memory does, and the response says locked:true|false. Every response carries result, the one field to branch on: 'stored' (a new row: id, and embedded, whether a vector was kept; truncated:true when content was shortened to the length cap; nodes:{status:'queued'} when the text runs past the embedding window and its overflow-tree nodes were queued), 'skipped' (nothing written and nothing wrong: a duplicate id, or content already stored under the same source id, echoes the existing row's id, except reason='duplicate (unique index)', a concurrent-write race, which has none), or 'rejected' (ok:false, nothing written; reason is human-readable, not a stable token). Under pause_persistence the write is skipped and the response carries persisted:false (id:'no-persist'), which tells a paused write from a duplicate. The older message={content, id, source, timestamp, metadata} form still works; use it or the top level, not both.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idNoOptional caller id: a later store with the same id in the same project is skipped as a duplicate.
lockNoAlso lock the memory against edits and deletion. Default false.
sourceNoWho produced the content, {type, id, name}. Default: {type:'Agent', id:<agent_id>}. Pass {} only when the producer is unknown.
channelNoMemory channel for context separation (e.g. 'chat'). Default: '' (shared).
contentNoThe text to store; a [Memory from …] annotation is removed anywhere in it, and text left empty is refused with ok:false, result:'rejected'.
messageNoThe older form of content, id, source, timestamp and metadata.
agent_idNoAgent identifier. May be omitted when this connection can write to exactly one agent.
metadataNoFree-form JSON, at most 8000 characters serialised (source has the same cap). Larger is rejected, not truncated.
timestampNoISO-8601 with an offset, e.g. '2026-07-22T12:00:00+00:00'. Default: now.
project_idNoIsolation bucket; omit or '' for the global pool (a recall in 'X' reads 'X' and the global pool). '@auto' resolves this agent's default from the operating context, echoed as resolved_project_id; with no operating context configured it is stored as the literal '@auto'.
session_keyNoOpaque session identity you declare: a partition hint, not authentication and not a data filter. Selects which no-persist pause applies to this call. Omit to share one bucket with every caller that omits it. Full text on recall.
associationsNoEntities and relations to declare against this memory, as declare_associations takes them: {entities: [{name, aliases}], relations: [{subject, predicate, object}]}, subject / object being entity names or 'mem:<id>' / 'ep:<id>' refs. Malformed items are reported in the response's associations.dropped and skipped; the memory is stored regardless.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed7 schema fields changedv2.6.12
    • addedInput schema / properties / channel / maxLength
      Added value: +256
    • changedInput schema / properties / content / description
      Previous value: -"The text to store. Content that is empty — or that sanitizes to empty — is refused with ok:false, result:'rejected'."New value: +"The text to store; a [Memory from …] annotation is removed anywhere in it, and text left empty is refused with ok:false, result:'rejected'."
    • addedInput schema / properties / id / maxLength
      Added value: +256
    • addedInput schema / properties / message / properties / id / maxLength
      Added value: +256
    • addedInput schema / properties / message / properties / timestamp / maxLength
      Added value: +64
    • addedInput schema / properties / project_id / maxLength
      Added value: +256
    • addedInput schema / properties / timestamp / maxLength
      Added value: +64
  2. Changed19 schema fields changedv2.6.10
    • changedInput schema / properties / agent_id / description
      Previous value: -"Agent identifier"New value: +"Agent identifier. May be omitted when this connection can write to exactly one agent."
    • changedInput schema / properties / associations / description
      Previous value: -"Associative memory to declare alongside this call: entities the text mentions, with their aliases, and subject–predicate–object relations. Stored verbatim; the server extracts nothing and infers nothing. On store, the stored memory is recorded as mentioning every entity named here and anchors every relation. Malformed items are reported in the response's associations.dropped and skipped; the memory is stored regardless. Optional."New value: +"Entities and relations to declare against this memory, as declare_associations takes them: {entities: [{name, aliases}], relations: [{subject, predicate, object}]}, subject / object being entity names or 'mem:<id>' / 'ep:<id>' refs. Malformed items are reported in the response's associations.dropped and skipped; the memory is stored regardless."
    • removedInput schema / properties / associations / properties
      Removed value: -{
      -  "entities": {
      -    "description": "Entities to register (if new) and mark as mentioned. Names and aliases are compared after normalization (NFKC, case-folded, whitespace collapsed), so two that normalize alike name one entity.",
      -    "items": {
      -      "properties": {
      -        "aliases": {
      -          "description": "Other names for the same entity. An alias resolves to at most one entity per scope; a second claim on it is dropped.",
      -          "items": {
      -            "type": "string"
      -          },
      -          "type": "array"
      -        },
      -        "name": {
      -          "description": "The canonical name, kept as written.",
      -          "type": "string"
      -        }
      -      },
      -      "required": [
      -        "name"
      -      ],
      -      "type": "object"
      -    },
      -    "type": "array"
      -  },
      -  "relations": {
      -    "description": "Declared relations. subject / object are entity names (registered if new) or record refs 'mem:<id>' / 'ep:<id>' of this agent; predicate is free text, normalized. A predicate from the role vocabulary (supports, supersedes, corrects, qualifies, contradicts, temporal_predecessor) on a record → record relation is read by reconstruct as that role.",
      -    "items": {
      -      "properties": {
      -        "object": {
      -          "type": "string"
      -        },
      -        "predicate": {
      -          "type": "string"
      -        },
      -        "subject": {
      -          "type": "string"
      -        }
      -      },
      -      "required": [
      -        "subject",
      -        "predicate",
      -        "object"
      -      ],
      -      "type": "object"
      -    },
      -    "type": "array"
      -  }
      -}
    • changedInput schema / properties / channel / description
      Previous value: -"Memory channel for context separation (e.g. 'chat', 'discord'). Default: '' (shared)."New value: +"Memory channel for context separation (e.g. 'chat'). Default: '' (shared)."
    • addedInput schema / properties / content
      Added value: +{
      +  "description": "The text to store. Content that is empty — or that sanitizes to empty — is refused with ok:false, result:'rejected'.",
      +  "type": "string"
      +}
    • addedInput schema / properties / id
      Added value: +{
      +  "description": "Optional caller id: a later store with the same id in the same project is skipped as a duplicate.",
      +  "type": "string"
      +}
    • addedInput schema / properties / lock
      Added value: +{
      +  "default": false,
      +  "description": "Also lock the memory against edits and deletion. Default false.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / message / description
      Previous value: -"ClotoMessage to store. Legacy source shapes are normalized server-side where unambiguous (e.g. lowercase type words, Rust serde externally-tagged dicts, bare 'user'/'assistant' strings); unknown shapes are stored verbatim and surfaced by check_health(invalid_source_type)."New value: +"The older form of content, id, source, timestamp and metadata."
    • removedInput schema / properties / message / properties / content / description
      Removed value: -"The text to store. Content that is empty — or that sanitizes to empty — is refused with ok:false, result:'rejected'."
    • removedInput schema / properties / message / properties / id / description
      Removed value: -"Caller-supplied message id used for msg_id-based dedup (γ-project-scoped). Optional."
    • removedInput schema / properties / message / properties / metadata / description
      Removed value: -"Free-form JSON object for producer-specific context. Empty when unused. Serialised size is capped at 8000 characters (same cap for source); an oversized field is refused with result='rejected' rather than truncated, because a truncated JSON document is not a JSON document."
    • changedInput schema / properties / message / properties / source / description
      Previous value: -"Attribution of who produced the content. Canonical shape is {type, id, name}. Type is the discriminator; id / name identify the concrete producer. Store null / empty {} only when the producer is genuinely unknown. A null source is normalized to {} at the write seam, so both persist (and recall) as the anonymous {}."New value: +"Also a bare 'user' / 'assistant' word, or null, stored as the anonymous {}."
    • removedInput schema / properties / message / properties / source / properties
      Removed value: -{
      -  "id": {
      -    "description": "Stable producer id (e.g. discord user id, agent id). Empty when anonymous.",
      -    "type": "string"
      -  },
      -  "name": {
      -    "description": "Human-readable label for display. Empty when unknown.",
      -    "type": "string"
      -  },
      -  "type": {
      -    "description": "Producer role — send one of 'User', 'Agent', 'System'. Legacy producers that cannot are folded server-side at the write seam ('ai' / 'assistant' are normalized to 'Agent'; 'session' is normalized to 'System' (type words are matched case-insensitively)), and shapes outside that table are stored verbatim for check_health(invalid_source_type) to surface.",
      -    "type": "string"
      -  }
      -}
    • removedInput schema / properties / message / properties / timestamp / description
      Removed value: -"UTC ISO-8601 timestamp with offset (e.g. '2026-07-22T12:00:00+00:00'). Defaults to server-time UTC when omitted. Aware non-UTC offsets are accepted; naive strings are surfaced by check_health(timestamp_format_drift)."
    • addedInput schema / properties / metadata
      Added value: +{
      +  "description": "Free-form JSON, at most 8000 characters serialised (source has the same cap). Larger is rejected, not truncated.",
      +  "type": "object"
      +}
    • changedInput schema / properties / project_id / description
      Previous value: -"v2.4.17 isolation axis. Optional — omit or pass '' to store in the global pool. Reads via γ semantics: a recall with project_id='X' returns 'X' rows + global pool. v2.5.1: pass '@auto' to resolve this agent's default from the server's operating context (the resolution is echoed as resolved_project_id; an unmapped agent yields operating_context_warning). bug-186: resolution requires a configured operating context. With none — the default, and equally the outcome of a sidecar that fails to parse — the sentinel is NOT resolved: it is stored and filtered as the literal project_id '@auto', resolved_project_id echoes '@auto', and no warning is raised. Read resolved_project_id before relying on the resolution."New value: +"Isolation bucket; omit or '' for the global pool (a recall in 'X' reads 'X' and the global pool). '@auto' resolves this agent's default from the operating context, echoed as resolved_project_id; with no operating context configured it is stored as the literal '@auto'."
    • addedInput schema / properties / source
      Added value: +{
      +  "description": "Who produced the content, {type, id, name}. Default: {type:'Agent', id:<agent_id>}. Pass {} only when the producer is unknown.",
      +  "properties": {
      +    "id": {
      +      "type": "string"
      +    },
      +    "name": {
      +      "type": "string"
      +    },
      +    "type": {
      +      "description": "One of 'User', 'Agent', 'System'; legacy spellings are folded ('ai' / 'assistant' are normalized to 'Agent'; 'session' is normalized to 'System' (type words are matched case-insensitively)).",
      +      "type": "string"
      +    }
      +  },
      +  "type": "object"
      +}
    • addedInput schema / properties / timestamp
      Added value: +{
      +  "description": "ISO-8601 with an offset, e.g. '2026-07-22T12:00:00+00:00'. Default: now.",
      +  "type": "string"
      +}
    • removedInput schema / required
      Removed value: -[
      -  "agent_id",
      -  "message"
      -]
  3. Changed2 schema fields changedv2.6.1
    • changedInput schema / properties / associations / properties / entities / description
      Previous value: -"Entities to register (if new) and mark as mentioned. Names are compared after normalization (NFKC, case-folded, whitespace collapsed)."New value: +"Entities to register (if new) and mark as mentioned. Names and aliases are compared after normalization (NFKC, case-folded, whitespace collapsed), so two that normalize alike name one entity."
    • addedInput schema / properties / session_key / maxLength
      Added value: +256
  4. Changed2 schema fields changedv2.5.12
    • addedInput schema / properties / associations
      Added value: +{
      +  "description": "Associative memory to declare alongside this call: entities the text mentions, with their aliases, and subject–predicate–object relations. Stored verbatim; the server extracts nothing and infers nothing. On store, the stored memory is recorded as mentioning every entity named here and anchors every relation. Malformed items are reported in the response's associations.dropped and skipped; the memory is stored regardless. Optional.",
      +  "properties": {
      +    "entities": {
      +      "description": "Entities to register (if new) and mark as mentioned. Names are compared after normalization (NFKC, case-folded, whitespace collapsed).",
      +      "items": {
      +        "properties": {
      +          "aliases": {
      +            "description": "Other names for the same entity. An alias resolves to at most one entity per scope; a second claim on it is dropped.",
      +            "items": {
      +              "type": "string"
      +            },
      +            "type": "array"
      +          },
      +          "name": {
      +            "description": "The canonical name, kept as written.",
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "name"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "relations": {
      +      "description": "Declared relations. subject / object are entity names (registered if new) or record refs 'mem:<id>' / 'ep:<id>' of this agent; predicate is free text, normalized. A predicate from the role vocabulary (supports, supersedes, corrects, qualifies, contradicts, temporal_predecessor) on a record → record relation is read by reconstruct as that role.",
      +      "items": {
      +        "properties": {
      +          "object": {
      +            "type": "string"
      +          },
      +          "predicate": {
      +            "type": "string"
      +          },
      +          "subject": {
      +            "type": "string"
      +          }
      +        },
      +        "required": [
      +          "subject",
      +          "predicate",
      +          "object"
      +        ],
      +        "type": "object"
      +      },
      +      "type": "array"
      +    }
      +  },
      +  "type": "object"
      +}
    • changedInput schema / properties / message / properties / source / type
      Previous value: -"object"New value: +[
      +  "object",
      +  "string",
      +  "null"
      +]
  5. Changed1 schema field changedv2.5.10
    • addedInput schema / properties / session_key
      Added value: +{
      +  "default": "",
      +  "description": "Opaque session identity you declare: a partition hint, not authentication and not a data filter. Selects which no-persist pause applies to this call. Omit to share one bucket with every caller that omits it. Full text on recall.",
      +  "type": "string"
      +}
  6. Changed2 schema fields changedv2.5.4
    • changedInput schema / properties / message / properties / source / properties / type / description
      Previous value: -"Producer role — this enum IS the contract; send one of these. Legacy producers that cannot are folded server-side at the write seam ('ai' / 'assistant' are normalized to 'Agent'; 'session' is normalized to 'System' (type words are matched case-insensitively)), and shapes outside that table are stored verbatim for check_health(invalid_source_type) to surface."New value: +"Producer role — send one of 'User', 'Agent', 'System'. Legacy producers that cannot are folded server-side at the write seam ('ai' / 'assistant' are normalized to 'Agent'; 'session' is normalized to 'System' (type words are matched case-insensitively)), and shapes outside that table are stored verbatim for check_health(invalid_source_type) to surface."
    • removedInput schema / properties / message / properties / source / properties / type / enum
      Removed value: -[
      -  "User",
      -  "Agent",
      -  "System"
      -]
  7. Changed4 schema fields changedv2.5.2
    • changedInput schema / properties / message / properties / content / description
      Previous value: -"The text to store. Empty content is skipped."New value: +"The text to store. Content that is empty — or that sanitizes to empty — is refused with ok:false, result:'rejected'."
    • changedInput schema / properties / message / properties / metadata / description
      Previous value: -"Free-form JSON object for producer-specific context. Empty when unused."New value: +"Free-form JSON object for producer-specific context. Empty when unused. Serialised size is capped at 8000 characters (same cap for source); an oversized field is refused with result='rejected' rather than truncated, because a truncated JSON document is not a JSON document."
    • changedInput schema / properties / message / properties / source / properties / type / description
      Previous value: -"Producer role. 'Assistant' / 'ai' are normalized to 'Agent'; 'session' is normalized to 'System'."New value: +"Producer role — this enum IS the contract; send one of these. Legacy producers that cannot are folded server-side at the write seam ('ai' / 'assistant' are normalized to 'Agent'; 'session' is normalized to 'System' (type words are matched case-insensitively)), and shapes outside that table are stored verbatim for check_health(invalid_source_type) to surface."
    • changedInput schema / properties / project_id / description
      Previous value: -"v2.4.17 isolation axis. Optional — omit or pass '' to store in the global pool. Reads via γ semantics: a recall with project_id='X' returns 'X' rows + global pool. v2.5.1: pass '@auto' to resolve this agent's default from the server's operating context (echoed as resolved_project_id)."New value: +"v2.4.17 isolation axis. Optional — omit or pass '' to store in the global pool. Reads via γ semantics: a recall with project_id='X' returns 'X' rows + global pool. v2.5.1: pass '@auto' to resolve this agent's default from the server's operating context (the resolution is echoed as resolved_project_id; an unmapped agent yields operating_context_warning). bug-186: resolution requires a configured operating context. With none — the default, and equally the outcome of a sidecar that fails to parse — the sentinel is NOT resolved: it is stored and filtered as the literal project_id '@auto', resolved_project_id echoes '@auto', and no warning is raised. Read resolved_project_id before relying on the resolution."
  8. Changed3 schema fields changedv2.5.1
    • changedInput schema / properties / message / description
      Previous value: -"ClotoMessage to store (id, content, source, timestamp, metadata)"New value: +"ClotoMessage to store. Legacy source shapes are normalized server-side where unambiguous (e.g. lowercase type words, Rust serde externally-tagged dicts, bare 'user'/'assistant' strings); unknown shapes are stored verbatim and surfaced by check_health(invalid_source_type)."
    • addedInput schema / properties / message / properties
      Added value: +{
      +  "content": {
      +    "description": "The text to store. Empty content is skipped.",
      +    "type": "string"
      +  },
      +  "id": {
      +    "description": "Caller-supplied message id used for msg_id-based dedup (γ-project-scoped). Optional.",
      +    "type": "string"
      +  },
      +  "metadata": {
      +    "description": "Free-form JSON object for producer-specific context. Empty when unused.",
      +    "type": "object"
      +  },
      +  "source": {
      +    "description": "Attribution of who produced the content. Canonical shape is {type, id, name}. Type is the discriminator; id / name identify the concrete producer. Store null / empty {} only when the producer is genuinely unknown. A null source is normalized to {} at the write seam, so both persist (and recall) as the anonymous {}.",
      +    "properties": {
      +      "id": {
      +        "description": "Stable producer id (e.g. discord user id, agent id). Empty when anonymous.",
      +        "type": "string"
      +      },
      +      "name": {
      +        "description": "Human-readable label for display. Empty when unknown.",
      +        "type": "string"
      +      },
      +      "type": {
      +        "description": "Producer role. 'Assistant' / 'ai' are normalized to 'Agent'; 'session' is normalized to 'System'.",
      +        "enum": [
      +          "User",
      +          "Agent",
      +          "System"
      +        ],
      +        "type": "string"
      +      }
      +    },
      +    "type": "object"
      +  },
      +  "timestamp": {
      +    "description": "UTC ISO-8601 timestamp with offset (e.g. '2026-07-22T12:00:00+00:00'). Defaults to server-time UTC when omitted. Aware non-UTC offsets are accepted; naive strings are surfaced by check_health(timestamp_format_drift).",
      +    "type": "string"
      +  }
      +}
    • changedInput schema / properties / project_id / description
      Previous value: -"v2.4.17 isolation axis. Optional — omit or pass '' to store in the global pool. Reads via γ semantics: a recall with project_id='X' returns 'X' rows + global pool."New value: +"v2.4.17 isolation axis. Optional — omit or pass '' to store in the global pool. Reads via γ semantics: a recall with project_id='X' returns 'X' rows + global pool. v2.5.1: pass '@auto' to resolve this agent's default from the server's operating context (echoed as resolved_project_id)."
  9. Changed1 schema field changedv2.4.34
    • addedInput schema / properties / project_id
      Added value: +{
      +  "description": "v2.4.17 isolation axis. Optional — omit or pass '' to store in the global pool. Reads via γ semantics: a recall with project_id='X' returns 'X' rows + global pool.",
      +  "type": "string"
      +}
  10. First observedv0.1.0

TDQS

A4.3/5.0
Behavior5/5

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

Beyond the annotations, the description discloses the full result branching contract: 'stored', 'skipped', and 'rejected', including duplicate handling, concurrent-race reason behavior, truncation, queued overflow nodes, and persisted:false under pause_persistence. It also explains that rejected responses are ok:false and not written. This is rich behavioral context that an agent cannot get from readOnlyHint/idempotentHint/destructiveHint alone.

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?

The description is front-loaded with the core action and then proceeds through defaults, result values, pause behavior, and the legacy form. It is dense and paragraph-shaped rather than cleanly sectioned, but nearly every sentence carries operational meaning for a 12-parameter tool. It is not padded with fluff.

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 12-parameter write tool with no output schema, the description covers the essential response semantics, duplicate/skip distinctions, pause_persistence interaction, lock echo, truncation, and legacy message form. The schema already documents the remaining parameter details at 100% coverage. An agent has enough information to call the tool and interpret the result correctly.

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 coverage is 100%, so the baseline would be 3. The description still adds cross-parameter meaning: agent_id omission is resolved and echoed as resolved_agent_id, source defaults to that agent, lock:true produces locked:true|false, and content is explicitly the text to store. It does not restate every schema detail, but it materially improves how the main parameters interact.

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

Purpose4/5

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

The description states a specific verb and resource: "Store a memory for future recall" and tells the caller to put the text in content. It also distinguishes the lock behavior from lock_memory, though it does not broadly route against all sibling write/update tools. The main action is unambiguous, but sibling differentiation is partial rather than complete.

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?

It explains when agent_id may be omitted, that source defaults to that agent, and that lock:true also locks the memory as lock_memory does. It also clarifies that the older message form still works but must not be combined with the top-level form. What is missing is explicit guidance on when to use store versus update_memory or import_memories.

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