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

# Artifacts

> Artifacts are the raw inputs gligabao ingests, and the source every entity and fact is traced back to.

An artifact is a piece of data ingested to be remembered: the raw text that `POST /v1/gb/remember` receives, stored as it came. It is the provenance of the graph: every entity and edge is anchored to the artifact(s) it was inferred from, so a fact can always be traced back to the original text.

Code: `internal/memory/memory_remember/remember.go` (`Remember`, `Store`, `ResolveKind`), `remember_chunks.go` (chunked texts), `remember_websearch.go` (web searches), `internal/db/graph/model/model.go` (types), `internal/db/graph/{sqlite,postgres}/db_schema.go` (tables).

Images are not artifacts in this sense: `remember` with an `image` stores an image artifact (a row in `gb_image_artifacts` tracking a file on disk) through a separate pipeline, and they are not linked to entities or edges yet (see [Images](https://gligabao.mintlify.site/guides/images.md)).

## Kinds

Every artifact has a `kind`, set by the optional `kind` field of the remember request:

| Kind | Meaning |
| - | - |
| `knowledge` (default) | Knowledge that is not strictly episodic: a reference text, a note, a description of how things are. Cognee-style memorization. |
| `episode` | A Graphiti-style episode: something written or observed at a point in time, such as a message or a news item. |

`kind` is trimmed and case-insensitive; an empty one means `knowledge`; any other value returns `400` and stores nothing.

Three more kinds exist but cannot be asked for: `web_search`, the result of a [web search](https://gligabao.mintlify.site/guides/web-search.md) that `remember` made (with `web_search`) for an entity of another artifact, `series_observation`, a text derived from a [timeseries](https://gligabao.mintlify.site/api-reference/timeseries.md#observations) (with `timeseries.observations`), and `chunk_summary`, the LLM-written [summary of a chunk](https://gligabao.mintlify.site/guides/chunking.md#chunk-summaries). The first two have a `query` and a parent (below); a summary has a parent and references the inference (model and reasoning level) that wrote it.

The kind is stored and returned, but it does not change how the text is extracted or reconciled yet. Both kinds get the same bi-temporal treatment (see [Temporal facts](https://gligabao.mintlify.site/concepts/temporal.md)). It exists so that behaviour can differ per kind later (for example, a `knowledge` artifact need not supersede older facts).

## Fields

Table `gb_artifacts`:

| Column | Meaning |
| - | - |
| `id` | The `artifact_id` returned by `remember` |
| `dataset_id` | The [dataset](https://gligabao.mintlify.site/concepts/datasets.md) it belongs to. Artifacts are never shared between datasets. |
| `kind` | `knowledge` or `episode` (`web_search`, `series_observation` and `chunk_summary` are created only by the pipeline) |
| `text` | The raw input, unchanged |
| `session_id` | The [session](https://gligabao.mintlify.site/concepts/sessions.md) that remembered it: the request's `session_id`, NULL if it had none |
| `valid_at` | Event time: when the text was written or observed. This is the request's `reference_time` (default: now). Relative dates in the text are resolved against it, and facts without a date of their own inherit it. |
| `created_at` | System time: when it was ingested |

\| `parent_id` | The artifact this one hangs off; NULL for an artifact that is nobody's child. Either the artifact it is a chunk of (see [Chunks](#chunks)), or, for a `web_search` artifact, the artifact the searched entity came from (see [Web searches](#web-searches)), or, for a `series_observation`, the artifact that anchors the series (see [Series observations](#series-observations)), or, for a `chunk_summary`, the chunk it summarizes (see [Chunk summaries](#chunk-summaries)) |
\| `chunk_index`, `start_offset`, `end_offset`, `tokens` | Only for a chunk: its position among its siblings (from 0), the byte range of its text in the parent's text, and its size in tokens |
\| `query` | Only for a `web_search` artifact: the web search query that was issued for it; for a `series_observation`, the series and window it is of |
\| `series_id` | Only for a `series_observation` artifact: the series it describes (`gb_series.id`; NULL if the series was deleted) |
\| `inference_id` | Only for a `chunk_summary` artifact: the run (`gb_inferences.id`, see [Inferences](https://gligabao.mintlify.site/operations/inferences.md)) of the model that wrote the summary; the run holds the model (`gb_models.id`) and the reasoning level it ran with (`none`, `low`, `medium` or `high`) |

Every `remember` call adds one artifact (plus, for a long text, its chunks), so sending the same text twice stores two artifacts. They add no duplicate entities or edges, but both are recorded as sources (below).

## Chunks

Artifacts can be the children of other artifacts. A text larger than one chunk (1024 tokens by default) is stored as an artifact holding the whole text, the **parent**, and is split into overlapping chunks that are artifacts too, its **children** (`parent_id` set; same `kind`, `session_id` and times; `text` is the chunk). Each chunk is extracted, stored and embedded individually, and the entities and edges link to the chunk they came from. A text that fits one chunk has no children. See [Chunking](https://gligabao.mintlify.site/guides/chunking.md).

## Chunk summaries

Each chunk of a chunked text is also summarized by an LLM, and the summary is stored as an artifact of its own, of kind `chunk_summary`: its **parent** (`parent_id`) is the chunk, so the chain is document, chunk, summary. It references the **inference** (`inference_id`: the model and the reasoning level) that wrote it, is embedded into the dataset's summary vector index, and, like a web search, is derived and not a chunk (no `chunk_index`). No entity or edge links to it. Everything is in [Chunking](https://gligabao.mintlify.site/guides/chunking.md#chunk-summaries).

## Web searches

With `web_search`, `remember` also searches the web for the latest world events about the key entities of the text, and stores each result as an artifact of its own, of kind `web_search`. It saves the **query** that was issued (`query`) and its **parent** (`parent_id`) is the artifact **from which the entity came**: the artifact the entity was extracted from, which for a long text is the chunk. A web search is therefore the second kind of child artifact; it is told apart from a chunk by its kind and by having no `chunk_index`. The entities and edges extracted from the result are linked to it like to any artifact (see below), so a fact learned on the web traces back to the query that found it and to the text whose entity was searched for. Everything is in [Web search](https://gligabao.mintlify.site/guides/web-search.md).

## Series observations

With `timeseries.observations`, `remember` derives a text from the stats of each timeseries it stored (generated in Go, not by an LLM) and stores it as an artifact of its own, of kind `series_observation`: it records the **series** it describes (`series_id`) and a `query` saying which series and window, and its **parent** (`parent_id`) is the artifact that anchors the series. It is the third kind of child artifact and, like a web search, is not a chunk (no `chunk_index`). The entities and edges extracted from its text link to it like to any artifact, so a fact derived from a series traces back to the observation, the series, and the text it was anchored to. Everything is in [Timeseries](https://gligabao.mintlify.site/api-reference/timeseries.md#observations).

## Provenance links

Entities and edges point back to their artifacts in three ways:

| Link | Cardinality | Records |
| - | - | - |
| `gb_edges.artifact_id` | an edge has one | The artifact that **created** the edge. Set to `NULL` if that artifact is deleted. |
| `gb_edge_artifacts` (`edge_id`, `artifact_id`) | many-to-many | The creating artifact **and every artifact whose duplicate of the fact was merged** into the edge. |
| `gb_entity_artifacts` (`entity_id`, `artifact_id`) | many-to-many | Every artifact that mentions the entity. |

Why link tables:

* **Entities** are deduplicated per dataset on (normalized name, type), so "Alice" mentioned in artifacts 1, 5 and 9 is one row. A single `artifact_id` column could only say where she first appeared. The link table also answers "which artifacts ground this entity?" and "which entities does this artifact contribute to?", and lets an artifact be removed without losing entities that other artifacts still support.
* **Edges** are created by one artifact, hence `artifact_id`. But when a later artifact states the same fact, the new edge is recognized as a duplicate (exactly, or by the LLM) and merged into the stored edge instead of being inserted. Without `gb_edge_artifacts` the fact that this artifact also supports it would be lost. The stored edge keeps its own `artifact_id`, `created_at` and `valid_at`.
* Contradicted edges are not linked to the artifact that contradicted them: a contradiction is not a restatement.

An entity is linked to an artifact whether it was created by it or already existed, and also when an edge names a stored entity the extraction did not list. Links are idempotent (primary key on the pair), and deleting either side removes only the link: deleting an entity cascades to its edges, and deleting an artifact sets `artifact_id` to `NULL` on its edges and removes its link rows.

Example. "Alice works at Acme" is remembered twice as artifacts 1 and 2:

| Table | Rows |
| - | - |
| `gb_edges` | one edge, `artifact_id = 1` |
| `gb_edge_artifacts` | (edge, 1), (edge, 2) |
| `gb_entity_artifacts` | (Alice, 1), (Alice, 2), (Acme, 1), (Acme, 2) |

## Sessions

An artifact carries the `session_id` of the `remember` call that created it, which connects the artifacts of one user/agent run (and, through `query`'s `session_id`, the queries). The session is also recorded against the entities and edges the artifact yields, in `gb_entity_sessions` and `gb_edge_sessions`, including entities and facts that already existed, so a session that only repeats known facts still leaves a trace. Image artifacts carry it too (`gb_image_artifacts.session_id`). See [Sessions](https://gligabao.mintlify.site/concepts/sessions.md).

## Where artifacts show up

* `POST /v1/gb/remember` returns the new `artifact_id`, its `kind`, `session_id` (if any), `valid_at` and `created_at` ([Remember](https://gligabao.mintlify.site/api-reference/remember.md)).
* Edges in the [graph export](https://gligabao.mintlify.site/api-reference/graph.md) and in the query `evidence` ([Query](https://gligabao.mintlify.site/api-reference/query.md)) carry `artifact_id` (the creating artifact).

## Limitations

* There is no endpoint to read, list or delete artifacts yet. The raw text can only be read from the database.
* `query` does not use artifact text: it answers from the graph only.
* The `gb_edge_artifacts` and `gb_entity_artifacts` links, and the session links (`gb_entity_sessions`, `gb_edge_sessions`), are stored but not exposed by the API yet.
* Artifacts are not embedded, except chunks: `remember` embeds the entities and edges extracted from an artifact, and the text of each chunk of a long text (see [Chunking](https://gligabao.mintlify.site/guides/chunking.md) and [Vector storage](https://gligabao.mintlify.site/guides/vectors.md)); the text of an artifact that is not chunked is not embedded.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.