# Getting started

> Give each of your users a memory, from a key to a prompt that knows them, in four steps.

Give each of your users a memory: write what they tell you, and put what is known about them in front of
your model. Four steps, and every snippet runs as printed.

```text
Add long-term memory to this project with Geniffy (docs: https://docs.geniffy.com).

1. Install the SDK for this project's language: `pip install geniffy` (Python) or `npm install geniffy`
   (TypeScript/JavaScript). Read the key from the GENIFFY_API_KEY environment variable; never hard-code
   it, never send it to a browser, and never log it.

2. Create one client for the process and reuse it: `Geniffy()` in Python (or `AsyncGeniffy()` in async
   code), `new Geniffy()` in TypeScript.

3. Give every end user their own memory. Where this app knows which user a request is for, bind a client
   to them once: `mem = client.space(f"user_{user_id}")` in Python, `const mem = client.space(`user_${userId}`)`
   in TypeScript, and use only `mem` below that point. A space is created by the first write to it.
   Never call memory methods on the unbound client for an end user's data: that writes to the account
   owner's own memory, where every user would be mixed together.

4. Save what is worth remembering. After a user tells the app something about themselves, their work or
   their plans, call `mem.memories.add(text)`. To save a whole conversation, pass it as the framework
   holds it: `mem.memories.add(messages=history)` / `mem.memories.add({ messages: history })`. Files:
   `memories.add_file(path)` / `memories.addFile(blob, { filename })` (PDF or Word .docx). Web pages:
   `memories.add(url=...)` / `memories.add({ url })`.

5. Use it before the model answers. Call `mem.context(user_question)` and put the string it returns above
   the user's message in the prompt. It is never empty: when nothing is known it returns a sentence that
   tells the model to say so, so pass it through as is and do not add a fallback. For a direct answer
   instead of context, use `mem.ask(question)`; when its `answer` is null, say nothing is known.

6. Let users be forgotten. Wherever this app deletes a user or their data, also call
   `client.forget_space(f"user_{user_id}")` / `client.forgetSpace(`user_${userId}`)`.

7. Handle errors: catch `AuthenticationError` (a wrong or revoked key) and `UnreadableError` (a file or
   link that could not be read; `error.source.error` says why). The SDK already retries busy and network
   errors. Log the `X-Request-ID` of any failed call: it finds the call on the Requests page.

8. Add one small test that writes a note into a test space, waits with `mem.sources.wait(id)`, checks that
   `mem.context(...)` mentions it, then erases the test space.

Keep the change minimal and match this project's style.
```

## Prerequisites

- A [Geniffy account](https://geniffy.com/app)
- [Python 3.9+](https://www.python.org/downloads/) or [Node.js 18+](https://nodejs.org/)

## Give your app a memory

From a key to a prompt that knows your user. Every call is plain HTTPS with a bearer key, so the curl tab
works from any language.

### 1. Get a key


Make one under **API keys** in the Geniffy app. It is shown once, so put it straight into an environment
variable. A key reaches your own memory and every space your code opens beneath it.

```bash
export GENIFFY_API_KEY="gnf_live_..."
```

### 2. Install the SDK


```bash
pip install geniffy
```

```bash
uv add geniffy
```

```bash
npm install geniffy
```

```bash
pnpm add geniffy
```

```bash
bun add geniffy
```

### 3. Remember something


Bind the client to one of your users with `space()`. Whatever you write through it is theirs alone: no
other space can read it, and neither can your own memory.

```python
from geniffy import Geniffy

client = Geniffy()                       # reads GENIFFY_API_KEY
mem = client.space("customer_1042")      # one of your users

source = mem.memories.add("Priya Nair signs the Lumen renewal, and it comes up in March.")
mem.sources.wait(source.id)              # learning usually takes a few seconds
```

```ts
import { Geniffy } from "geniffy";

const client = new Geniffy();                  // reads GENIFFY_API_KEY
const mem = client.space("customer_1042");     // one of your users

const source = await mem.memories.add("Priya Nair signs the Lumen renewal, and it comes up in March.");
await mem.sources.wait(source.id);             // learning usually takes a few seconds
```

```bash
curl https://api.geniffy.com/v1/memories \
  -H "Authorization: Bearer $GENIFFY_API_KEY" \
  -H "X-Geniffy-Space: customer_1042" \
  -H "Content-Type: application/json" \
  -d '{"text": "Priya Nair signs the Lumen renewal, and it comes up in March."}'
```

Geniffy reads what you add and keeps each fact in it as its own memory, with what you added as its source.

### 4. Put what it knows in your prompt


`context()` returns the memories that bear on a question, already written out for a prompt, each line
saying where it came from.

```python
context = mem.context("Who signs the Lumen renewal?")
prompt = f"{context}\n\nUser: Who signs the Lumen renewal?"
```

```ts
const context = await mem.context("Who signs the Lumen renewal?");
const prompt = `${context}\n\nUser: Who signs the Lumen renewal?`;
```

```bash
curl https://api.geniffy.com/v1/context \
  -H "Authorization: Bearer $GENIFFY_API_KEY" \
  -H "X-Geniffy-Space: customer_1042" \
  -H "Content-Type: application/json" \
  -d '{"question": "Who signs the Lumen renewal?"}'
```

What comes back:

```text
- Priya Nair signs the Lumen renewal.  [note, 2026-10-05]
- The Lumen renewal comes up in March 2027.  [note, 2026-10-05]
```

Each line says where it came from and when. Dates are kept as dates: "comes up in March", written in
October, is held as March 2027. The wording of each memory is Geniffy's own, so yours may read a little
differently.


See the [Python](https://docs.geniffy.com/sdks/python) and [TypeScript](https://docs.geniffy.com/sdks/typescript) SDKs for every call.

## When nothing is known, it says so

Ask about something that was never stored and `context()` returns one sentence instead of an empty
string:

```text
There is nothing stored about this yet. Say so rather than guessing.
```

A model reads silence as permission to invent. This keeps it honest, and it is the same judgement `ask()`
makes. See [When nothing is known](https://docs.geniffy.com/recall/when-nothing-is-known).

## Next steps

- [Keys and spaces](https://docs.geniffy.com/keys-and-spaces): one memory per user, and the one mistake to avoid
- [Add memories](https://docs.geniffy.com/add-memories): conversations, files, web pages and batches
- [Recall](https://docs.geniffy.com/recall): when to use context, ask or search
- [Production checklist](https://docs.geniffy.com/production-checklist): what to set before your app goes live
- [Errors and limits](https://docs.geniffy.com/errors): what can go wrong, and how to find any call again

Source: https://docs.geniffy.com/getting-started
