> ## Documentation Index
> Fetch the complete documentation index at: https://docs.memloom.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Run the consolidation pass

> Reviews the store, repairs what SQL proves wrong, folds duplicate entity names, and
asks about the rest. Every run is one undoable unit: the report names the run id, and
`/memory/reconcile/{id}/revert` puts back exactly what it did.

`mode` defaults to `dry_run`, which changes nothing and never calls a model, returning
what the paid passes would have cost in `estimate`. **The `memloom reconcile` CLI
command defaults the other way and applies.**

Passes come from the saved settings unless `passes` overrides them: two free ones on,
three paid ones off. With the contradiction re-check on a run takes minutes, so use the
stream variant rather than holding this request open. See
[Reconciliation](https://docs.memloom.dev/concepts/reconciliation).




## OpenAPI

````yaml /openapi.yaml post /memory/reconcile
openapi: 3.1.0
info:
  title: memloom local API
  version: 0.1.0
  description: >
    The HTTP API served by the `memloom serve` daemon on your machine. The CLI,
    the MCP server,

    and the viewer all route through this API. The daemon is the single owner of
    the store, so

    every client shares one consistent view of your memories.


    No authentication: the daemon binds to `127.0.0.1` only and is reachable
    solely from your

    own machine. Browser clients on other localhost ports are allowed via CORS.
servers:
  - url: http://127.0.0.1:4319
    description: Local memloom daemon
security: []
paths:
  /memory/reconcile:
    post:
      summary: Run the consolidation pass
      description: >
        Reviews the store, repairs what SQL proves wrong, folds duplicate entity
        names, and

        asks about the rest. Every run is one undoable unit: the report names
        the run id, and

        `/memory/reconcile/{id}/revert` puts back exactly what it did.


        `mode` defaults to `dry_run`, which changes nothing and never calls a
        model, returning

        what the paid passes would have cost in `estimate`. **The `memloom
        reconcile` CLI

        command defaults the other way and applies.**


        Passes come from the saved settings unless `passes` overrides them: two
        free ones on,

        three paid ones off. With the contradiction re-check on a run takes
        minutes, so use the

        stream variant rather than holding this request open. See

        [Reconciliation](https://docs.memloom.dev/concepts/reconciliation).
      operationId: reconcile
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ReconcileInput'
      responses:
        '200':
          description: What the run found and what it changed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReconcileReport'
        '400':
          $ref: '#/components/responses/ValidationError'
        '403':
          description: >
            `RECONCILE_ENABLED=0` is set on the daemon and `mode` is `apply`.
            The kill switch

            refuses any run that was asked to act; a dry run still works.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: >-
                      reconciliation is set to report only
                      (RECONCILE_ENABLED=0). Remove it from your memloom config
                      and restart the daemon to let a run act.
        '409':
          description: >-
            Another applying run is already going. Watch it or wait for it to
            finish.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: >-
                      memloom: a reconcile run is already going. Watch it in the
                      Console, or wait for it to finish.
components:
  schemas:
    ReconcileInput:
      type: object
      description: What to run. Every field is optional.
      properties:
        mode:
          type: string
          enum:
            - dry_run
            - apply
          default: dry_run
          description: >-
            `dry_run` reports and changes nothing, and never calls a model.
            `apply` acts.
        trigger:
          type: string
          enum:
            - manual
            - idle
            - startup
          default: manual
          description: Recorded on the run, so the history says who started it.
        passes:
          type: array
          description: >-
            Run exactly these passes, ignoring the saved settings. Omit to use
            the settings, which is what every shipped surface does. This
            overrides the settings for the three paid passes too, so a caller
            can start a run that spends money while the Settings toggles are
            off. `RECONCILE_ENABLED=0` still refuses it.
          items:
            type: string
            enum:
              - invariants
              - entities
              - llm_entities
              - llm_conflicts
              - llm_recheck
        budgetUsd:
          type: number
          exclusiveMinimum: 0
          maximum: 50
          description: >-
            Keep re-checking past the per-run ceiling until nothing is due or
            this much has been billed, measured against the provider's own
            reported cost. Omit for one page and stop, which is the default.
            Capped at 50 because a typo here spends real money.
    ReconcileReport:
      type: object
      description: >-
        One run's own words. This is what the CLI prints and the Settings tab
        renders.
      properties:
        run:
          $ref: '#/components/schemas/ReconcileRun'
        actions:
          type: array
          items:
            $ref: '#/components/schemas/ReconcileAction'
        estimate:
          $ref: '#/components/schemas/ReconcileEstimate'
        passes:
          type: array
          items:
            type: string
          description: The passes this run actually ran.
        heldBack:
          type: object
          description: >-
            Findings recorded but not surfaced, because a per-run cap was
            reached.
          properties:
            retire:
              type: integer
            question:
              type: integer
            conflict:
              type: integer
        entities:
          $ref: '#/components/schemas/EntityResolutionResult'
        arbitration:
          type: object
          description: Present when the uncertain entity pairs pass ran.
          properties:
            calls:
              type: integer
            folded:
              type: integer
            rejected:
              type: integer
              description: >-
                Pairs the model said are different things. Recorded, so it is
                never asked again.
            unsure:
              type: integer
              description: Left pending for a human.
        autoResolved:
          type: object
          description: Present when the memory conflicts pass ran.
          properties:
            examined:
              type: integer
            resolved:
              type: integer
        recheck:
          type: object
          description: Present when the contradiction re-check ran.
          properties:
            window:
              type: integer
              description: Beliefs this run swept.
            calls:
              type: integer
            claimed:
              type: integer
              description: >-
                Contradictions the model claimed, before the quotes were
                checked.
            verified:
              type: integer
              description: >-
                Findings whose quotes were found in both memories, and were
                recorded.
            remaining:
              type: integer
              description: Beliefs still due when the run stopped.
            spentUsd:
              type: number
              description: Billed for this pass, from the provider's own figures.
            spentInputTokens:
              type: integer
            spentOutputTokens:
              type: integer
            stoppedBy:
              type: string
              nullable: true
              enum:
                - budget
                - aborted
                - cap
                - unpriced
                - failed
              description: >-
                Why it stopped short. `cap` is the per-run ceiling with no
                budget set, `budget` is the spend limit, `aborted` is a stop,
                `unpriced` means a budget was set but the provider reported no
                cost so the run refused to page on blind, and `failed` means
                every call in a page failed. Null means nothing is due any more.
    ReconcileRun:
      type: object
      description: One run, and what it did.
      properties:
        id:
          type: string
          format: uuid
        mode:
          type: string
          enum:
            - dry_run
            - apply
        trigger:
          type: string
          enum:
            - manual
            - idle
            - startup
        status:
          type: string
          enum:
            - running
            - success
            - error
            - aborted
        scanned:
          type: integer
          description: Active memories the run looked at.
        retired:
          type: integer
          description: Memories staled. Never deleted, and undo puts them back.
        folded:
          type: integer
          description: Entities folded into another.
        questions:
          type: integer
          description: Findings reported rather than fixed.
        conflictsRaised:
          type: integer
        possible:
          type: integer
          description: >-
            Unconfirmed contradictions the re-check recorded. Not conflicts
            until a human says so.
        llmCalls:
          type: integer
        spentUsd:
          type: number
          description: >-
            What the run actually cost, from the provider's own billed figures.
            Written per call, so it survives a crash mid-sweep.
        spentInputTokens:
          type: integer
        spentOutputTokens:
          type: integer
        error:
          type: string
          nullable: true
          description: Why a run with status `error` failed. Null otherwise.
        startedAt:
          type: string
          format: date-time
        finishedAt:
          type: string
          format: date-time
          nullable: true
        revertedAt:
          type: string
          format: date-time
          nullable: true
    ReconcileAction:
      type: object
      description: One thing a run found.
      properties:
        id:
          type: string
          format: uuid
        runId:
          type: string
          format: uuid
        kind:
          type: string
          enum:
            - retire
            - question
            - conflict
            - fold
            - possible
          description: >-
            `retire` and `fold` changed state. `question` and `conflict` ask
            you. `possible` is an unconfirmed contradiction from the re-check.
        class:
          type: string
          description: The detector behind it.
          example: duplicate_content
        memoryId:
          type: string
          format: uuid
          nullable: true
        reason:
          type: string
          example: identical content to 41b0e2d8, which is older and stays active
        applied:
          type: boolean
          description: True only when an applying run actually changed something here.
        surfaced:
          type: boolean
          description: False when the finding was recorded but held back by a per-run cap.
        decision:
          type: string
          enum:
            - approved
            - rejected
            - snoozed
          nullable: true
        mergeId:
          type: string
          format: uuid
          nullable: true
          description: On a fold, the merge record the undo reverses.
        conflictId:
          type: string
          format: uuid
          nullable: true
          description: On a conflict, the queue row this finding became.
        candidateId:
          type: string
          format: uuid
          nullable: true
          description: On a possible contradiction, the older belief of the pair.
        createdAt:
          type: string
          format: date-time
    ReconcileEstimate:
      type: object
      description: >-
        What re-checking everything currently due would cost, from the real
        prompt template and the actual content lengths. A dry run reports this
        instead of spending it. One run is capped at 200 beliefs, so on a store
        with a backlog this is what several runs add up to.
      properties:
        window:
          type: integer
          description: Active memories due a contradiction re-check.
        llmCalls:
          type: integer
          description: One per memory in the window.
        inputTokens:
          type: integer
        outputTokens:
          type: integer
        model:
          type: string
          example: google/gemini-2.5-flash
        usd:
          type: number
          nullable: true
          description: >-
            Null for a model whose rates memloom does not know, rather than a
            confident wrong number.
    EntityResolutionResult:
      type: object
      description: What one resolution pass did.
      properties:
        examined:
          type: integer
          description: Entities considered.
        pairs:
          type: integer
          description: Pairs that survived bucketing and were judged.
        merged:
          type: integer
          description: Folds applied without asking.
        queued:
          type: integer
          description: Uncertain folds written to the conflicts queue.
        deferred:
          type: integer
          description: >-
            Uncertain folds not written because the queue is already full.
            Reported rather than dropped silently, so "nothing queued" never
            hides "there was more to ask about". A later pass picks them up.
        skipped:
          type: integer
          description: Pairs already merged, queued, or settled as distinct.
  responses:
    ValidationError:
      description: The request body failed validation. `issues` names each offending field.
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: invalid request body
              issues:
                type: array
                items:
                  type: object
                  properties:
                    path:
                      type: string
                      example: query
                    message:
                      type: string
                      example: query must be a non-empty string

````