> For the complete documentation index, see [llms.txt](https://docs.telys.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.telys.ai/quickstarts/quickstart-first-collection.md).

# First collection

Go from `pip install` to a saved, searchable collection. Install the CLI, sign in to activate the runtime, then use the Python SDK to create a collection, add documents, search them, and save to disk.

{% hint style="info" %}
`import telys` works without the runtime, but every collection operation loads the signed native runtime lazily, and `AlgentaMultigramEmbedder` needs the native kernel. `telys login` installs both. Without them you see `RuntimeNotInstalled` (engine) or `ImportError` (embedder). See [Verify your install](/start-here/verify-install.md).
{% endhint %}

{% stepper %}
{% step %}

#### Install the CLI

`pipx` isolates the CLI in its own environment; `pip` installs it into the current one.

{% tabs %}
{% tab title="pipx" icon="terminal" %}

```bash
pipx install telys
```

Preferred: puts `telys` on your PATH without touching your project's dependencies.
{% endtab %}

{% tab title="pip" icon="python" %}

```bash
pip install telys
```

Use `pip` to make `telys` importable in the same environment as your application code.
{% endtab %}
{% endtabs %}

Confirm the version:

```bash
telys version
```

**Expected result:**

```
telys 0.1.0b2 (format v1)
```

{% endstep %}

{% step %}

#### Sign in and install the runtime

The SDK is a thin wrapper over a signed native runtime. `telys login` authenticates you (browser device-code flow by default) and installs the runtime for the free `telys_developer` plan.

```bash
telys login
```

For headless machines or CI, pass a token instead of opening a browser:

```bash
telys login --token $TELYS_TOKEN
```

Confirm the runtime is present and its signature verifies:

```bash
telys runtime verify
```

{% hint style="success" %}
`telys login` with no flags provisions the free `telys_developer` tier: one device, on-device, no card required. Add `--plan telys_pro` for the commercial tier.
{% endhint %}
{% endstep %}

{% step %}

#### Create a collection

A collection lives under a store directory. `Telys("./memory")` creates that directory and loads the runtime on demand. `create_collection` builds and caches the collection in memory; it does **not** write to disk yet.

```python
from telys import Telys
from telys.embedding import AlgentaMultigramEmbedder

t = Telys("./memory")

# Lexical, on-device embedder. Its dimension is read from the native kernel,
# so let it define the collection's dimension rather than hard-coding a number.
emb = AlgentaMultigramEmbedder()

col = t.create_collection(
    "notes",
    dim=emb.profile.dimension,
    partition_by="scope",
    embedder=emb,
    # Only declared filter_columns are stored and returned by with_metadata=True.
    # List "scope" too so the partition key comes back in each hit's metadata.
    filter_columns=("scope", "category"),
)
```

`partition_by="scope"` names the metadata field used as each record's physical partition key. Every record you add must carry that field.
{% endstep %}

{% step %}

#### Add a few documents

`add_texts` embeds each string and inserts it as a **new** row. `ids` are your own external identifiers; `metadata` is a per-row payload that must include the partition field (`scope`).

```python
col.add_texts(
    texts=[
        "Telys keeps every vector on your own machine, offline by default.",
        "A collection is written to disk only when you call save().",
        "The signed runtime is a native library loaded on demand.",
    ],
    ids=["doc-1", "doc-2", "doc-3"],
    metadata=[
        {"scope": "notes", "category": "storage"},
        {"scope": "notes", "category": "lifecycle"},
        {"scope": "notes", "category": "runtime"},
    ],
)
```

{% hint style="warning" %}
`add_texts` inserts new rows only and raises `KeyError` if an id already exists. To replace existing rows, use `upsert_texts` — see [Add & upsert records](/working-with-data/add-and-upsert.md).
{% endhint %}
{% endstep %}

{% step %}

#### Search the collection

`search_text` embeds the query with the same embedder and returns the closest ids and their scores. Pass `with_metadata=True` to include each hit's payload.

```python
results = col.search_text(
    "how do I write a collection to disk?",
    top_k=3,
    with_metadata=True,
)
print(results)
```

**Expected result:**

```
{'ids': ['doc-2', 'doc-1', 'doc-3'],
 'scores': [0.68, 0.21, 0.14],
 'metadata': [{'scope': 'notes', 'category': 'lifecycle'},
              {'scope': 'notes', 'category': 'storage'},
              {'scope': 'notes', 'category': 'runtime'}]}
```

`ids` and `scores` are aligned and sorted best-first. Scores are the inner product of L2-normalized vectors (cosine similarity): higher means more similar, and `1.0` is an identical match. Because `AlgentaMultigramEmbedder` is lexical, the top hit is the sentence that shares the most words and character n-grams with the query.
{% endstep %}

{% step %}

#### Persist to disk

Nothing so far survives the process. `save()` writes the id-map sidecar, then `collection.json` (the commit point), and returns the collection's directory.

```python
path = col.save()
print(path)

# Only saved collections show up here:
print(t.collections())
```

**Expected result:**

```
./memory/notes
['notes']
```

Reopen it later in a fresh process, passing the same embedder. `open_collection` only auto-attaches an embedder you registered earlier with `register_provider`:

```python
from telys import Telys
from telys.embedding import AlgentaMultigramEmbedder

t = Telys("./memory")
col = t.open_collection("notes", embedder=AlgentaMultigramEmbedder())
print(len(col))   # 3
```

{% endstep %}
{% endstepper %}

{% hint style="danger" %}
`create_collection` never touches disk on its own. If your process exits before `save()`, the collection and everything you added are gone, and `t.collections()` will not list it. Treat `save()` as the commit — call it after a batch of writes. See [Snapshots & persistence](/working-with-data/snapshots-and-persistence.md).
{% endhint %}

## Troubleshooting

<details>

<summary><code>RuntimeNotInstalled</code> on the first collection call</summary>

The signed runtime is not installed or not verified. Run `telys login`, then `telys runtime verify`. See [Install & runtime issues](/troubleshooting/install-and-runtime.md).

</details>

<details>

<summary><code>ImportError</code> when constructing <code>AlgentaMultigramEmbedder</code></summary>

The lexical embedders need the native kernel that ships with the verified runtime. Confirm the runtime is installed (`telys runtime status`), or point Telys at a kernel with `$TELYS_KERNEL`. See [Embedding dimension mismatches](/troubleshooting/dimension-mismatches.md).

</details>

<details>

<summary><code>KeyError</code> from <code>add_texts</code></summary>

One of the `ids` already exists. `add_texts` only inserts new rows. Use `upsert_texts` to insert-or-replace, or pick fresh ids.

</details>

## Next steps

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Semantic search</strong></td><td>Build a small searchable text index and filter the results.</td><td><a href="/pages/tZvLrbDjBo9peIumbpSE">/pages/tZvLrbDjBo9peIumbpSE</a></td></tr><tr><td><strong>Agent memory</strong></td><td>Give an AI agent durable, per-user memory with scope keys.</td><td><a href="/pages/PAT4pDE2TcuVbgRbANvN">/pages/PAT4pDE2TcuVbgRbANvN</a></td></tr><tr><td><strong>Collections</strong></td><td>Understand the collection model, partitions, and the on-disk layout.</td><td><a href="/pages/ZBd4ROKi3CD4dcp51PD4">/pages/ZBd4ROKi3CD4dcp51PD4</a></td></tr><tr><td><strong>Create a collection</strong></td><td>The full guide to every create_collection option.</td><td><a href="/pages/EIWgp0wPwoYMjxP37Daw">/pages/EIWgp0wPwoYMjxP37Daw</a></td></tr></tbody></table>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.telys.ai/quickstarts/quickstart-first-collection.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
