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

# Chat with your documents

> Upload a file, wait for extraction, ask. Uploads land in the same space as everything else you recorded.

[← All use cases](/use-cases/overview)

<div className="uc-examples"><a href="https://github.com/anonalabs/Anona-Memory-SDK/blob/main/examples/document_qa.py">document\_qa.py</a></div>

## The scenario

Half of what your agent should know is in files — a policy, a spec, a handbook.
You do not want a second retrieval system for them, and you do not want to
pre-chunk anything.

Uploads land in the same space as recorded memories, so one `retrieve` answers
from both.

## Step 1 — Upload

```python theme={null}
job = client.upload_file(space_id=space, file="refund-policy.txt")
```

`file` takes a path, raw bytes, or a file object. PDF, DOCX, PPTX, XLSX, HTML,
TXT/MD/CSV, images, MP3/WAV audio and MP4/MOV/WEBM/MKV video are all read into
text.

## Step 2 — Wait for it to be searchable

Ingestion is asynchronous. The upload returns job ids; `completed` means that
file is searchable.

```python theme={null}
for job_id in job["job_ids"]:
    while client.get_job(space_id=space, job_id=job_id)["status"] not in ("completed", "failed"):
        time.sleep(5)
```

In production use [webhooks](/use-cases/events-not-polling) instead of a loop.

## Step 3 — Ask, and see which file answered

```python theme={null}
for row in client.retrieve(space_id=space, query="How long do I have to return hardware?"):
    print(row["content"], "from", row.get("document_id"))
```

## Step 4 — The document stays a first-class object

```python theme={null}
for doc in client.list_documents(space_id=space):
    print(doc["document_id"], "->", doc["memory_count"], "memories")
```

Deleting a document removes every memory extracted from it in one call — which
is what makes "remove that outdated policy" a single operation rather than a
hunt.

## Evals

1. Upload one file you know the answers in. Ask three questions from it.
2. Ask something the file does not cover. Empty is correct.
3. Check `document_id` resolves on every answer you would act on.
4. Delete the document and re-ask. Everything from it should be gone.

## Guardrails

* **A question asked seconds after upload may legitimately find nothing.** Wait
  for `completed`; do not treat the gap as a bug.
* **Per-file limits apply** — 25 MB generally, 64 MB for video, with request
  totals above that. One oversized file rejects the whole request.
* **Uploads take scope too.** Pass `tags` on upload if later reads will be
  scoped, or the document is invisible to every scoped query.

## The script

Complete and runnable:
[`document_qa.py`](https://github.com/anonalabs/Anona-Memory-SDK/blob/main/examples/document_qa.py).
