# System Tags Reference

System tags are automatically managed metadata prefixed with underscore (`_`). Users cannot set or modify these tags directly - they are protected by the `filter_non_system_tags()` function in `keep/types.py`.

## Implemented Tags

These tags are actively set and maintained by the system.

### `_created`

**Purpose:** ISO 8601 timestamp of when the item was first indexed.

**Set by:** `DocumentStore.upsert()` in `document_store.py`, `ChromaStore.upsert()` in `store.py`

**Behavior:** Set once on first insert, preserved on updates. Both stores maintain this independently.

**Example:** `"2026-01-15T10:30:00.123456+00:00"`

**Access:** Read via `item.created` property or `item.tags["_created"]`

---

### `_updated`

**Purpose:** ISO 8601 timestamp of the last modification.

**Set by:** `DocumentStore.upsert()` in `document_store.py`, `ChromaStore.upsert()` in `store.py`

**Behavior:** Updated on every modification (content, summary, or tags). Both stores maintain this independently.

**Example:** `"2026-02-02T14:45:00.789012+00:00"`

**Access:** Read via `item.updated` property or `item.tags["_updated"]`

---

### `_updated_date`

**Purpose:** Date portion of `_updated` for efficient date-based queries.

**Set by:** `DocumentStore.upsert()` in `document_store.py`, `ChromaStore.upsert()` in `store.py`

**Behavior:** Always set alongside `_updated`. Format: `YYYY-MM-DD`. Both stores maintain this independently.

**Example:** `"2026-02-02"`

**Usage:** Used by `--since` filtering in CLI commands.

---

### `_accessed`

**Purpose:** ISO 8601 timestamp of when the item was last retrieved (read).

**Set by:** `_record_to_item()` in `api.py`, from `accessed_at` column in `DocumentStore`

**Behavior:** Updated whenever the item is retrieved via `get()` or `find()`. Distinct from `_updated` — reading an item updates `_accessed` but not `_updated`.

**Example:** `"2026-02-07T09:15:00.123456+00:00"`

**Access:** Read via `item.accessed` property or `item.tags["_accessed"]`

---

### `_accessed_date`

**Purpose:** Date portion of `_accessed` for efficient date-based queries.

**Set by:** `_record_to_item()` in `api.py`

**Behavior:** Always set alongside `_accessed`. Format: `YYYY-MM-DD`.

**Example:** `"2026-02-07"`

---

### `_content_type`

**Purpose:** MIME type of the document content.

**Set by:** `Keeper.put()` in `api.py` (only for URI-based documents)

**Behavior:** Set if the document provider returns a content type.

**Example:** `"text/markdown"`, `"text/html"`, `"application/pdf"`, `"audio/mpeg"`, `"image/jpeg"`

**Note:** Not set for inline content (CLI: `keep put "text"`, API: `kp.put("text")`).

---

### `_source`

**Purpose:** How the content was obtained.

**Set by:** `Keeper.put()` in `api.py`

**Values:**
- `"uri"` - Content fetched from a URI (CLI: `keep put <uri>`, API: `kp.put(uri=...)`)
- `"inline"` - Inline content (CLI: `keep put "text"`, API: `kp.put("text")`)
- `"langchain"` - Created by KeepStore (LangChain/LangGraph integration)

**Usage:** Query with `kp.list_items(tags={"_source": "inline"})` to find remembered content.

---

## Protection Mechanism

System tags are protected from user modification:

```python
# In keep/types.py
SYSTEM_TAG_PREFIX = "_"

def filter_non_system_tags(tags: dict[str, str]) -> dict[str, str]:
    """Filter out any system tags (those starting with '_')."""
    return {k: v for k, v in tags.items() if not k.startswith(SYSTEM_TAG_PREFIX)}
```

This function is called before merging user-provided tags in `put()` and `tag()` methods.

## Tag Merge Order

When indexing documents, tags are merged in this order (later wins on collision):

1. **Existing tags** - Preserved from previous version
2. **Config tags** - From `[tags]` section in `keep.toml`
3. **Environment tags** - From `KEEP_TAG_*` variables
4. **User tags** - Passed to `put()` or `tag()`
5. **System tags** - Added/updated by system (cannot be overridden)

## Querying by System Tags

```python
# Find items by source
inline_items = kp.list_items(tags={"_source": "inline"})
uri_items = kp.list_items(tags={"_source": "uri"})

# Find items by date
today = kp.list_items(tags={"_updated_date": "2026-02-02"})

# Find system documents
system_docs = kp.list_items(tags={"_system": "true"})
```

## Versioning and System Tags

When a document is updated, the previous version (including all its system tags) is archived in the `document_versions` table. This preserves the complete tag state at each point in history.

```python
# Current version has current timestamps
current = kp.get("doc:1")
print(current.tags["_updated"])  # "2026-02-02T14:45:00..."

# Previous version has its own timestamps
prev = kp.get_version("doc:1", offset=1)
print(prev.tags["_updated"])  # "2026-02-01T10:30:00..."
```

## See Also

- [REFERENCE.md](REFERENCE.md) - API reference card
- [QUICKSTART.md](QUICKSTART.md) - Getting started guide
- [ARCHITECTURE.md](ARCHITECTURE.md) - System architecture
