{
  "description": "Save durable facts to persistent memory that survive across sessions. Memory is injected into every future turn, so keep entries compact and high-signal.\n\nHOW: make ALL your changes to one target in ONE call via an 'operations' array (each item: {action, content?, old_text?}). The batch applies atomically and the char limit is checked only on the FINAL result — so a single call can remove/patch stale entries to free room AND add new ones, even when an add alone would overflow. The response reports current/limit chars and confirms completion; one batch call finishes the update, so don't repeat it. Use the bare action/content/old_text fields only for a single lone change.\n\nWHEN: only for facts that apply to EVERY session regardless of task: who the user is, stable environment facts, standing conventions with no task home. Anything learned while doing a task (procedures, pitfalls, and the user's preferences and corrections for that kind of work) belongs in the task's skill via skill_manage, where it loads only when relevant; memory is injected into every turn and must stay small.\n\nIF FULL: an add is rejected with the current entries shown. Reissue as ONE batch that removes or shortens enough stale entries and adds the new one together.\n\nTARGETS: 'user' = who the user is (name, role, preferences, style). 'memory' = your notes (environment, conventions, tool quirks, lessons).\n\nSKIP: trivial/obvious info, easily re-discovered facts, raw data dumps, task progress, completed-work logs, temporary TODO state (use session_search for those). Reusable procedures belong in a skill, not memory.",
  "name": "memory",
  "parameters": {
    "properties": {
      "action": {
        "description": "The action to perform (single-op shape). Omit when using 'operations'.",
        "enum": [
          "add",
          "patch",
          "remove"
        ],
        "type": "string"
      },
      "content": {
        "description": "Required for 'add' and 'patch'. For 'add', the new entry. For 'patch', the text that replaces old_text; the rest of the entry is kept. Alias: 'new_text'.",
        "type": "string"
      },
      "new_text": {
        "description": "Alias for 'content'. If both are set, 'content' wins.",
        "type": "string"
      },
      "old_text": {
        "description": "REQUIRED for 'patch' and 'remove': text from one entry. 'patch' replaces exactly this span (it must occur once in the entry); 'remove' deletes the whole entry. Omit for 'add'.",
        "type": "string"
      },
      "operations": {
        "description": "Batch shape: a list of operations applied atomically in one call against the final char budget. Preferred when making multiple changes or consolidating to make room. Each item is {action, content?, old_text?}.",
        "items": {
          "additionalProperties": false,
          "properties": {
            "action": {
              "enum": [
                "add",
                "patch",
                "remove"
              ],
              "type": "string"
            },
            "content": {
              "description": "Required for add and patch, as 'content' above.",
              "type": "string"
            },
            "new_text": {
              "description": "Alias for 'content' in a batch op.",
              "type": "string"
            },
            "old_text": {
              "description": "As 'old_text' above.",
              "type": "string"
            }
          },
          "required": [
            "action"
          ],
          "type": "object"
        },
        "type": "array"
      },
      "target": {
        "description": "Which memory store: 'memory' for personal notes, 'user' for user profile.",
        "enum": [
          "memory",
          "user"
        ],
        "type": "string"
      }
    },
    "required": [
      "target"
    ],
    "type": "object"
  }
}
