# AUTO-GENERATED tier-A mirror spec — do not edit.
# Source: openapi/runtime/memory-stores.yaml (runtime 0.71.2)
#  + policy: openapi/mirror-policies/memory-stores.json
# Regenerate: node scripts/generate-mirror-specs.mjs
openapi: 3.0.3
info:
  title: naturali.ai — Memory Stores API
  version: 1.0.0
  description: >-
    Memory stores: the named stores an agent remembers into and reads back from — the other half of
    the retrieval an agent's knowledge configuration performs, alongside the project's documents. A
    fully runtime-backed module — this spec is generated verbatim from the runtime's own, re-rooted
    under /v1/projects/{project_id}. The project in the path is authorized by naturali and enforced
    upstream by the project's scoped credential.


    This module mirrors the upstream runtime verbatim (tier A, #304): paths are the runtime's own
    re-rooted under /v1/projects/{project_id}, and every field, method, status code and error shape
    passes through unchanged. Errors raised by the runtime arrive in its envelope; errors raised by
    naturali itself (authentication, project resolution, an unreachable runtime) use naturali's.
  contact:
    name: naturali.ai
    url: https://naturali.ai
servers:
  - url: "{baseUrl}"
    description: Host of your naturali.ai deployment; every path carries the /v1 prefix.
    variables:
      baseUrl:
        description: Base host URL.
        default: https://api.naturali.ai
tags:
  - name: MemoryStores
    description: Manage memory store configurations for document retrieval
security:
  - bearerAuth: []
  - oauth2:
      - mcp:access
paths:
  /v1/projects/{project_id}/memory-stores:
    get:
      tags:
        - MemoryStores
      summary: List memory stores
      description: Returns a list of memory store configurations for a project
      operationId: listMemoryStores
      parameters:
        - $ref: "#/components/parameters/TagsQuery"
        - name: limit
          in: query
          required: false
          description: Maximum number of results to return
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
        - name: offset
          in: query
          required: false
          description: Number of results to skip
          schema:
            type: integer
            default: 0
      responses:
        "200":
          description: List of memory stores
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                  - total
                  - limit
                  - offset
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/MemoryStore"
                  total:
                    type: integer
                  limit:
                    type: integer
                  offset:
                    type: integer
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "500":
          description: Internal server error
    post:
      tags:
        - MemoryStores
      summary: Create a memory store
      description: Creates a new memory store configuration in a project
      operationId: createMemoryStore
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
              additionalProperties: false
              properties:
                name:
                  type: string
                  description: Memory store name
                  example: Product Documentation
                description:
                  type: string
                  description: Optional description
                  example: Retrieves product docs for support queries
                tags:
                  description: Optional key-value tags. Scopes the memory store in knowledge search, where every
                    requested pair must match exactly.
                  allOf:
                    - $ref: "#/components/schemas/TagBag"
                duplicate_threshold:
                  type: number
                  nullable: true
                  description: "The store's dedup policy: cosine similarity at or above which an incoming fact is
                    already known and the write is skipped. `null` (the default) uses the algorithm
                    constant `0.95`. A single `POST /v1/projects/{project_id}/memories` call may
                    override it; the agent tool and the post-turn rule never can."
                  minimum: 0
                  maximum: 1
                  example: 0.95
                supersede_threshold:
                  type: number
                  nullable: true
                  description: "Cosine similarity at or above which an incoming fact restates a known one that has
                    changed: the matched memory is invalidated and replaced. `null` (the default)
                    uses the algorithm constant `0.90`. Must be lower than the effective
                    `duplicate_threshold`, or the write is rejected with `400 VALIDATION_FAILED` —
                    equal makes `superseded` unreachable and inverted swallows `skipped`."
                  minimum: 0
                  maximum: 1
                  example: 0.9
      responses:
        "201":
          description: Memory store created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MemoryStore"
        "400":
          description: Bad request — a missing required field, a threshold outside `[0, 1]`, or a pair that is
            not `supersede_threshold < duplicate_threshold`.
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "500":
          description: Internal server error
    parameters:
      - $ref: "#/components/parameters/ProjectId"
  /v1/projects/{project_id}/memory-stores/{memory_store_id}:
    get:
      tags:
        - MemoryStores
      summary: Get a memory store
      description: Returns a single memory store configuration by ID
      operationId: getMemoryStore
      x-naturali-resource:
        kind: memory_store
        from: memory_store_id
      parameters:
        - name: memory_store_id
          in: path
          required: true
          schema:
            type: string
            example: mstore_V1StGXR8Z5jdHi6B
      responses:
        "200":
          description: Memory store found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MemoryStore"
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Memory store not found
        "500":
          description: Internal server error
    put:
      tags:
        - MemoryStores
      summary: Update a memory store
      description: Updates an existing memory store configuration
      operationId: updateMemoryStore
      x-naturali-resource:
        kind: memory_store
        from: memory_store_id
      parameters:
        - name: memory_store_id
          in: path
          required: true
          schema:
            type: string
            example: mstore_V1StGXR8Z5jdHi6B
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              additionalProperties: false
              properties:
                name:
                  type: string
                  description: Memory store name
                description:
                  type: string
                  nullable: true
                  description: Optional description
                tags:
                  description: Optional key-value tags. Replaces the stored bag; `null` clears it.
                  allOf:
                    - $ref: "#/components/schemas/NullableTagBag"
                duplicate_threshold:
                  type: number
                  nullable: true
                  description: "The store's dedup policy: cosine similarity at or above which an incoming fact is
                    already known and the write is skipped. `null` (the default) uses the algorithm
                    constant `0.95`. A single `POST /v1/projects/{project_id}/memories` call may
                    override it; the agent tool and the post-turn rule never can."
                  minimum: 0
                  maximum: 1
                  example: 0.95
                supersede_threshold:
                  type: number
                  nullable: true
                  description: "Cosine similarity at or above which an incoming fact restates a known one that has
                    changed: the matched memory is invalidated and replaced. `null` (the default)
                    uses the algorithm constant `0.90`. Must be lower than the effective
                    `duplicate_threshold`, or the write is rejected with `400 VALIDATION_FAILED` —
                    equal makes `superseded` unreachable and inverted swallows `skipped`."
                  minimum: 0
                  maximum: 1
                  example: 0.9
      responses:
        "200":
          description: Memory store updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MemoryStore"
        "400":
          description: Bad request — a threshold outside `[0, 1]`, or a pair that is not `supersede_threshold
            < duplicate_threshold` once the stored values this request does not replace are applied.
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Memory store not found
        "500":
          description: Internal server error
    delete:
      tags:
        - MemoryStores
      summary: Delete a memory store
      description: Deletes a memory store configuration
      operationId: deleteMemoryStore
      x-naturali-resource:
        kind: memory_store
        from: memory_store_id
      parameters:
        - name: memory_store_id
          in: path
          required: true
          schema:
            type: string
            example: mstore_V1StGXR8Z5jdHi6B
      responses:
        "204":
          description: Memory store deleted
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Memory store not found
        "500":
          description: Internal server error
    parameters:
      - $ref: "#/components/parameters/ProjectId"
  /v1/projects/{project_id}/memory-stores/{memory_store_id}/assertions:
    get:
      tags:
        - MemoryStores
      summary: List a memory store's write assertions
      description: "Returns the store's write ledger, newest first: one row per write attempt, skips
        included. This is how \"which write path is filling this store?\" is asked — a question no
        column on a memory row could answer, because a skipped write produced no memory at all."
      operationId: listMemoryStoreAssertions
      x-naturali-resource:
        kind: memory_store
        from: memory_store_id
      x-iam-action: memories:ListMemoryAssertions
      parameters:
        - name: memory_store_id
          in: path
          required: true
          schema:
            type: string
            example: mstore_V1StGXR8Z5jdHi6B
        - name: mechanism
          in: query
          required: false
          description: Only assertions that came through this door.
          schema:
            type: string
            enum:
              - tool
              - rule
              - api
              - formation
        - name: outcome
          in: query
          required: false
          description: Only assertions that resolved this way.
          schema:
            type: string
            enum:
              - created
              - superseded
              - skipped
        - name: generation_id
          in: query
          required: false
          description: Only assertions made during this generation. A generation that does not exist matches
            nothing rather than widening to the whole store.
          schema:
            type: string
            example: gen_V1StGXR8Z5jdHi6B
        - name: since
          in: query
          required: false
          description: Only assertions recorded at or after this instant.
          schema:
            type: string
            format: date-time
        - name: limit
          in: query
          required: false
          description: Maximum number of results to return
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
        - name: offset
          in: query
          required: false
          description: Number of results to skip
          schema:
            type: integer
            default: 0
      responses:
        "200":
          description: List of assertions
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                  - total
                  - limit
                  - offset
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/MemoryAssertion"
                  total:
                    type: integer
                  limit:
                    type: integer
                  offset:
                    type: integer
        "400":
          description: An unknown `mechanism` or `outcome`, or a `since` that is not a timestamp
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Memory store not found
        "500":
          description: Internal server error
    parameters:
      - $ref: "#/components/parameters/ProjectId"
  /v1/projects/{project_id}/memory-stores/{memory_store_id}/export:
    get:
      tags:
        - MemoryStores
      summary: Export a memory store's memories as NDJSON
      description: Streams one store's memories as newline-delimited JSON — one memory object per line,
        oldest first. Invalidated memories (retracted or superseded) are left out unless
        `include_invalidated` asks for them, so the file holds what the store currently asserts. The
        rows are the rows the listing returns for the same caller.
      operationId: exportMemories
      x-naturali-resource:
        kind: memory_store
        from: memory_store_id
      x-mcp-exclude: true
      parameters:
        - name: memory_store_id
          in: path
          required: true
          description: Memory store whose memories are exported
          schema:
            type: string
            example: mem_store_V1StGXR8Z5jdHi6B
        - name: include_invalidated
          in: query
          description: Include memories that were retracted or superseded
          schema:
            type: boolean
            default: false
        - $ref: "#/components/parameters/TagsQuery"
      responses:
        "200":
          description: A newline-delimited stream of memories. Each line is a JSON object with the same fields
            as `Memory`.
          content:
            application/x-ndjson:
              schema:
                type: string
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Memory store not found
    parameters:
      - $ref: "#/components/parameters/ProjectId"
  /v1/projects/{project_id}/memory-stores/{memory_store_id}/tags:
    get:
      tags:
        - MemoryStores
      summary: Get memory store tags
      description: Returns all tags attached to the memory store
      operationId: getMemoryStoreTags
      x-naturali-resource:
        kind: memory_store
        from: memory_store_id
      x-iam-action: memories:GetMemoryStore
      parameters:
        - name: memory_store_id
          in: path
          required: true
          description: Memory store ID
          schema:
            type: string
            example: mstore_V1StGXR8Z5jdHi6B
      responses:
        "200":
          description: Memory store tags
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TagBag"
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Memory store not found
    put:
      tags:
        - MemoryStores
      summary: Replace memory store tags
      description: Replaces all tags on the memory store with the provided tags (not merged)
      operationId: replaceMemoryStoreTags
      x-naturali-resource:
        kind: memory_store
        from: memory_store_id
      x-iam-action: memories:UpdateMemoryStore
      parameters:
        - name: memory_store_id
          in: path
          required: true
          description: Memory store ID
          schema:
            type: string
            example: mstore_V1StGXR8Z5jdHi6B
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TagBag"
      responses:
        "200":
          description: Tags replaced
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TagBag"
        "400":
          description: Body is not an object of string values
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Memory store not found
    patch:
      tags:
        - MemoryStores
      summary: Merge memory store tags
      description: Merges provided tags into the memory store's existing tags (existing tags are preserved
        unless overridden)
      operationId: mergeMemoryStoreTags
      x-naturali-resource:
        kind: memory_store
        from: memory_store_id
      x-iam-action: memories:UpdateMemoryStore
      parameters:
        - name: memory_store_id
          in: path
          required: true
          description: Memory store ID
          schema:
            type: string
            example: mstore_V1StGXR8Z5jdHi6B
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TagBag"
      responses:
        "200":
          description: Tags merged
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TagBag"
        "400":
          description: Body is not an object of string values
        "401":
          description: Unauthorized
        "403":
          description: Forbidden
        "404":
          description: Memory store not found
    parameters:
      - $ref: "#/components/parameters/ProjectId"
components:
  schemas:
    MemoryStore:
      type: object
      properties:
        id:
          type: string
          example: mstore_V1StGXR8Z5jdHi6B
        project_id:
          x-naturali-ref: projects
          type: string
          example: proj_V1StGXR8Z5jdHi6B
        name:
          type: string
          example: Product Documentation
        description:
          type: string
          nullable: true
          example: Retrieves product docs for support queries
        tags:
          description: Key-value tags for filtering in knowledge search.
          allOf:
            - $ref: "#/components/schemas/NullableTagBag"
        duplicate_threshold:
          type: number
          nullable: true
          description: "The store's duplicate cutoff, or `null` when it has never been set. Reported as `null`
            rather than as the constant it resolves to: a store with no policy must read differently
            from one pinned to today's default."
          example: 0.95
        supersede_threshold:
          type: number
          nullable: true
          description: The store's supersede cutoff, or `null` when it has never been set.
          example: 0.9
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    TagBag:
      type: object
      additionalProperties:
        type: string
      x-cli-flag-name: tags
      description: >-
        Key-value labels on a resource. A flat object of string values — an array, a nested object
        or a number is rejected with `400 VALIDATION_FAILED`, never coerced. Keys are opaque and
        stored verbatim, so `cost_center` and `costCenter` are two different tags. Matched by JSONB
        containment wherever tags are read: the `?tags=` filter and knowledge search.


        Keys beginning `system.` are reserved: the platform writes them to record which
        conversation, actor, agent and role a row came from, and a write naming one is refused with
        `400 RESERVED_TAG_KEY`. They are read and filtered like any other tag.


        The bag is bounded, because every pair reaches the IAM context of every access check on the
        resource: at most 50 keys, each key at most 128 characters and each value at most 256. A
        write past a bound — including a merge that would grow the stored bag past the key count —
        is `400 VALIDATION_FAILED` with `meta.limit` naming the bound it crossed. `system.*` keys
        are the platform's and do not count against the 50.
      example:
        team: finance
        env: prod
    NullableTagBag:
      type: object
      nullable: true
      additionalProperties:
        type: string
      description: A `TagBag` on a field where `null` is meaningful — a full-replacement update that
        clears the bag, or a record whose bag was never set.
      example:
        team: finance
        env: prod
    MemoryAssertion:
      type: object
      description: "One write attempt against a memory store: some principal, through some mechanism,
        claimed a fact. Append-only, and recorded whatever the outcome — including the skips, which
        left no record anywhere before."
      properties:
        id:
          type: string
          example: massert_V1StGXR8Z5jdHi6B
        memory_store_id:
          x-naturali-ref: memory-stores
          type: string
          example: mstore_V1StGXR8Z5jdHi6B
        memory_id:
          type: string
          nullable: true
          description: "The memory this assertion resolved into: the new memory for `created` and
            `superseded`, the existing memory that matched for `skipped`, the memory withdrawn for
            `retracted`. Null only once that memory has been deleted."
          example: mem_V1StGXR8Z5jdHi6B
        superseded_memory_id:
          type: string
          nullable: true
          description: The memory this assertion retired, on a `superseded` outcome; null otherwise, a
            retraction included — it retires its own memory, which `memory_id` already names. Read
            back from `memories.superseded_by_memory_id` rather than stored here, because validity
            lives on the memory — where every read filters it — and exactly one memory is superseded
            per assertion.
          example: mem_V1StGXR8Z5jdHi6B
        content:
          type: string
          description: "The text as asserted, which is not necessarily the memory's text: a `skipped`
            assertion records what was claimed, while the memory keeps what it already held."
          example: The customer prefers email communication over phone calls
        mechanism:
          type: string
          enum:
            - tool
            - rule
            - api
            - formation
          description: Which door the write came through. `tool` is the agent's `write_memory` call mid-turn;
            `rule` is a post-turn pass over the finished turn; `api` is `POST
            /v1/projects/{project_id}/memories`; `formation` is a `memory` resource in an applied
            template. It answers *how*, never *who* — the principal fields answer that.
          example: tool
        rule_id:
          x-naturali-ref: memory-rules
          type: string
          nullable: true
          description: The memory rule whose firing wrote this, set only when `mechanism` is `rule` — the
            built-in extractor included, since that is a rule with no handler. Null once the rule
            has been deleted, and on assertions written before memory rules shipped.
          example: mrule_V1StGXR8Z5jdHi6B
        generation_id:
          x-naturali-ref: generations
          type: string
          nullable: true
          description: The turn that asserted the fact — the origin of anything an agent wrote, and the edge a
            conversation is reachable from. Null on the `api` and `formation` doors, which have no
            generation behind them.
          example: gen_V1StGXR8Z5jdHi6B
        principal_type:
          type: string
          description: Who claimed the fact, in the vocabulary a generation records its starter with, plus
            `agent`. On both agent doors the principal is the agent itself — the extractor runs
            under its identity.
          example: agent
        principal_id:
          type: string
          example: agent_V1StGXR8Z5jdHi6B
        outcome:
          type: string
          enum:
            - created
            - superseded
            - skipped
            - retracted
          description: What the write resolved to. `created` is a distinct fact, `superseded` is the same fact
            changed (the top match was invalidated and replaced), `skipped` is a fact already known,
            `retracted` is a fact that stopped holding with nothing replacing it.
          example: created
        similarity:
          type: number
          nullable: true
          description: The cosine similarity the outcome was decided against — the top match's, or the
            declared target's when `declared` is true, where it decides nothing and only records how
            far apart the two statements were. Null when there was nothing to compare against, when
            the content could not be embedded, and on a `retracted` outcome, which compares nothing.
          example: 0.97
        declared:
          type: boolean
          description: Whether the write named the memory it replaced (`supersedes` on create) instead of the
            thresholds choosing one. Always false on a `created`, `skipped` or `retracted` outcome.
          example: false
        created_at:
          type: string
          format: date-time
  parameters:
    ProjectId:
      name: project_id
      in: path
      required: true
      description: Project public ID (proj_ prefix).
      schema:
        type: string
        example: proj_V1StGXR8Z5jdHi6B
    TagsQuery:
      name: tags
      in: query
      required: false
      description: >
        Filter by tag pairs, written `key:value` (split on the first colon, so a value may contain
        colons). Repeat the parameter for several pairs; **all** must be present with exactly that
        value.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
      example:
        - env:prod
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: A naturali API key (nat_sk_…) or a session JWT.
    oauth2:
      type: oauth2
      description: "A connected app's OAuth access token, issued by this API's authorization server
        (discovery: /.well-known/oauth-authorization-server). Its one scope carries every operation,
        confined to the projects the user chose when approving the app."
      flows:
        authorizationCode:
          authorizationUrl: https://api.naturali.ai/authorize
          tokenUrl: https://api.naturali.ai/token
          refreshUrl: https://api.naturali.ai/token
          scopes:
            mcp:access: Every operation this API serves, on the projects the grant covers.
