openapi: 3.0.3
info:
  title: SOAT Memory Entries API
  version: 1.0.0
  description: API for managing individual memory entries within a memory container
  contact:
    name: SOAT Team
    url: https://github.com/ttoss/soat
servers:
  - url: '{baseUrl}'
    description: Base URL of your SOAT deployment
    variables:
      baseUrl:
        description: The base URL of your SOAT deployment
        default: http://localhost:5047
tags:
  - name: Memory Entries
    description: Manage individual memory entries (the actual knowledge items stored in a memory)
security:
  - bearerAuth: []
paths:
  /api/v1/memory-entries:
    get:
      tags:
        - Memory Entries
      summary: List memory entries
      description: Returns all entries in a memory container
      operationId: listMemoryEntries
      x-iam-action: memories:ListMemoryEntries
      parameters:
        - name: memory_id
          in: query
          required: true
          description: Memory container to list entries from (mem_...)
          schema:
            type: string
            example: mem_V1StGXR8Z5jdHi6B
        - name: limit
          in: query
          required: false
          description: Maximum number of results to return
          schema:
            type: integer
            default: 50
        - name: offset
          in: query
          required: false
          description: Number of results to skip
          schema:
            type: integer
            default: 0
        - name: include_invalidated
          in: query
          required: false
          description: Include invalidated (superseded) entries. They are excluded by default; set this to audit the supersede history.
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: List of memory entries
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                  - total
                  - limit
                  - offset
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/MemoryEntry'
                  total:
                    type: integer
                  limit:
                    type: integer
                  offset:
                    type: integer
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
        '404':
          description: Memory not found
        '500':
          description: Internal server error
    post:
      tags:
        - Memory Entries
      summary: Create a memory entry
      description: >-
        Creates a new entry in the specified memory container. Automatically
        generates an embedding for semantic search, and skips the write when an
        existing entry is a near-duplicate (see `duplicate_threshold`). A merely
        similar fact is stored as its own entry: this path has no agent context
        and therefore no model to consolidate two facts into one.
      operationId: createMemoryEntry
      x-iam-action: memories:CreateMemoryEntry
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - memory_id
                - content
              properties:
                memory_id:
                  x-soat-ref: memories
                  type: string
                  description: Memory container to add the entry to (mem_...)
                  example: mem_V1StGXR8Z5jdHi6B
                content:
                  type: string
                  description: The text content of the memory entry
                  example: The customer prefers email communication over phone calls
                source_type:
                  type: string
                  enum: [manual, agent, extraction, orchestration]
                  description: How this entry was created
                  default: manual
                  example: manual
                tags:
                  type: array
                  items:
                    type: string
                  description: Per-entry tag strings, used for entry-granularity filtering in search-knowledge (memory_tags)
                  example: [role:traffic-manager, source:rejected_approval]
                metadata:
                  type: object
                  additionalProperties: true
                  description: Arbitrary structured metadata attached to the entry
                  example: { evidence: high, quarter: Q3 }
                duplicate_threshold:
                  type: number
                  description: Cosine similarity score at or above which the incoming content is considered a duplicate of an existing entry and skipped (default 0.95). Below it the entry is always created.
                  default: 0.95
                  minimum: 0
                  maximum: 1
      responses:
        '200':
          description: Memory entry deduplicated (action is "skipped")
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemoryEntryWriteResult'
        '201':
          description: Memory entry created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemoryEntryWriteResult'
        '400':
          description: Bad request (missing required fields)
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
        '404':
          description: Memory not found
        '500':
          description: Internal server error
  /api/v1/memory-entries/{entry_id}:
    get:
      tags:
        - Memory Entries
      summary: Get a memory entry
      description: Returns a single memory entry by ID
      operationId: getMemoryEntry
      x-iam-action: memories:GetMemoryEntry
      parameters:
        - name: entry_id
          in: path
          required: true
          schema:
            type: string
            example: mem_entry_V1StGXR8Z5jdHi6B
      responses:
        '200':
          description: Memory entry found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemoryEntry'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
        '404':
          description: Memory or entry not found
        '500':
          description: Internal server error
    put:
      tags:
        - Memory Entries
      summary: Update a memory entry
      description: Updates an existing memory entry. Regenerates the embedding if content changes.
      operationId: updateMemoryEntry
      x-iam-action: memories:UpdateMemoryEntry
      parameters:
        - name: entry_id
          in: path
          required: true
          schema:
            type: string
            example: mem_entry_V1StGXR8Z5jdHi6B
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                content:
                  type: string
                  description: Updated text content
                tags:
                  type: array
                  nullable: true
                  items:
                    type: string
                  description: Replaces the entry's tags. Pass null or an empty array to clear.
                  example: [role:traffic-manager]
                metadata:
                  type: object
                  nullable: true
                  additionalProperties: true
                  description: Replaces the entry's metadata. Pass null to clear.
      responses:
        '200':
          description: Memory entry updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MemoryEntry'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
        '404':
          description: Memory or entry not found
        '500':
          description: Internal server error
    delete:
      tags:
        - Memory Entries
      summary: Delete a memory entry
      description: Deletes a memory entry
      operationId: deleteMemoryEntry
      x-iam-action: memories:DeleteMemoryEntry
      parameters:
        - name: entry_id
          in: path
          required: true
          schema:
            type: string
            example: mem_entry_V1StGXR8Z5jdHi6B
      responses:
        '204':
          description: Memory entry deleted
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
        '404':
          description: Memory or entry not found
        '500':
          description: Internal server error
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    MemoryEntry:
      type: object
      properties:
        id:
          type: string
          example: mem_entry_V1StGXR8Z5jdHi6B
        memory_id:
          x-soat-ref: memories
          type: string
          example: mem_V1StGXR8Z5jdHi6B
        content:
          type: string
          example: The customer prefers email communication over phone calls
        source_type:
          type: string
          enum: [manual, agent, extraction, orchestration]
          example: manual
        tags:
          type: array
          nullable: true
          items:
            type: string
          description: Per-entry tag strings
          example: [role:traffic-manager, source:rejected_approval]
        metadata:
          type: object
          nullable: true
          additionalProperties: true
          description: Arbitrary structured metadata attached to the entry
          example: { evidence: high }
        source_generation_id:
          x-soat-ref: generations
          type: string
          nullable: true
          description: The generation whose turn produced this entry. Set for entries written by the `write_memory` tool and by automatic extraction; null for manual and orchestration writes. Recorded when the entry is created and never rewritten by a later merge.
          example: gen_V1StGXR8Z5jdHi6B
        source_conversation_id:
          x-soat-ref: conversations
          type: string
          nullable: true
          description: The conversation the producing turn belonged to. Null when the entry did not come from a conversation (a direct agent generation, a manual write, or an orchestration write).
          example: conv_V1StGXR8Z5jdHi6B
        invalidated_at:
          type: string
          format: date-time
          nullable: true
          description: When the entry was superseded. Null means the entry is currently valid. Invalidated entries are excluded from listing, from write deduplication, and from knowledge search, but remain readable by ID for audit.
        superseded_by_entry_id:
          type: string
          nullable: true
          description: The entry that replaced this one, when it was superseded. Null for valid entries.
          example: mem_entry_V1StGXR8Z5jdHi6B
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    MemoryEntryWriteResult:
      allOf:
        - $ref: '#/components/schemas/MemoryEntry'
        - type: object
          properties:
            action:
              type: string
              enum: [created, updated, skipped, superseded]
              description: >-
                The outcome of the write operation. `updated` means an existing
                entry was rewritten to absorb the incoming fact — it is produced
                only by the LLM consolidation on agent write paths (the
                `write_memory` tool and automatic extraction), never by this
                endpoint, which creates instead of merging. `superseded` means
                the incoming content contradicted an existing entry, which was
                invalidated and replaced — it is produced by the LLM-arbitrated
                write path and does not occur until that ships.
