# Knowledge bases

Source: https://docs.usetone.ai/knowledge-bases

> Documents an agent can answer from, without putting them in the prompt.

A knowledge base is a set of documents an agent retrieves from mid-call.
Attaching one is how an agent answers "what's your returns window?" without that
answer living in the prompt.

## The shape of it

```bash
# 1. create
curl "$TONE_API/v1/knowledge-bases" -X POST \
  -H "Authorization: Bearer $TONE_KEY" -H 'content-type: application/json' \
  -d '{"name":"Shipping and returns policy"}'

# 2. import a page, or upload a file (see below)
curl "$TONE_API/v1/knowledge-bases/$KB/documents/url" -X POST \
  -H "Authorization: Bearer $TONE_KEY" -H 'content-type: application/json' \
  -d '{"url":"https://example.com/help/returns"}'

# 3. attach it to an agent
curl "$TONE_API/v1/agents/$AGENT" -X PATCH \
  -H "Authorization: Bearer $TONE_KEY" -H 'content-type: application/json' \
  -d "{\"knowledgeBaseIds\":[\"$KB\"]}"
```

## Builds are asynchronous

Indexing runs in the background and swaps atomically — the old index keeps
serving until the new one succeeds. Status is derived, not stored:

| Status | Meaning |
|---|---|
| `empty` | No documents yet |
| `indexing` | A build is running; the previous index still answers |
| `ready` | At least one build has succeeded |
| `error` | The last build failed. The previous index, if any, still answers |

**Subscribe to `knowledge.build.completed` and `knowledge.build.failed` rather
than polling.** Attaching a base that has never built successfully and then
dialling gives `409 knowledge_base_not_ready` — there is nothing to answer from.

## Uploading a file

Uploads are two-phase, because nothing about a file is trusted until we have read
it ourselves:

1. `POST /documents/upload-url` — declare the filename, type and **exact** byte
   length. The length is signed into the URL; a presigned PUT that does not pin
   it is an unbounded write.
2. `PUT` the bytes to the URL you get back.
3. `POST /documents/{id}/confirm` — we re-read the object, check its real size
   and type against what you declared, and queue it for indexing.

## Test what the agent will actually get

```bash
curl "$TONE_API/v1/knowledge-bases/$KB/search" -X POST \
  -H "Authorization: Bearer $TONE_KEY" -H 'content-type: application/json' \
  -d '{"query":"How long do I have to return an item?"}'
```

This runs the **same retrieval a live turn runs** — a preview that queried
differently would be worse than no preview. It optionally generates the answer a
caller would hear.

`degraded: true` in the response means embeddings were unavailable and it fell
back to keyword search alone. The results are real, just weaker.

## Writing documents that retrieve well

Retrieval works on passages, so structure beats prose. Headings that name the
question ("Returns window", "COD refunds") retrieve far better than a wall of
text, because the heading travels with the passage.
