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

# Knowledge Bases

> Create and manage RAG-style knowledge bases programmatically.

The `KnowledgeBases` module is the entry point for managing knowledge bases: vector stores backed by uploaded documents. Use it to list existing KBs, load one, or create a new KB. The actual document operations (`add_documents`, `search`, `list_documents`, `delete`) live on the `KnowledgeBase` instance.

```python theme={"dark"}
from xpander_sdk import KnowledgeBases

kbs = KnowledgeBases()

# Create
kb = await kbs.acreate(name="Q4 Reports", description="Quarterly earnings")

# Add documents
await kb.aadd_documents([
    "https://example.com/Q4-2024.pdf",
    "https://example.com/Q4-2025.pdf",
])

# Search
results = await kb.asearch(search_query="revenue trends", top_k=5)
for r in results:
    print(r.score, r.content[:80])
```

## Constructor

```python theme={"dark"}
KnowledgeBases(configuration: Optional[Configuration] = None)
```

| Parameter       | Type            | Default | Description                                |
| --------------- | --------------- | ------- | ------------------------------------------ |
| `configuration` | `Configuration` | `None`  | SDK configuration. Falls back to env vars. |

## Module methods

| Method                                                                   | Returns               | What it does                   |
| ------------------------------------------------------------------------ | --------------------- | ------------------------------ |
| [`alist` / `list`](/developers/sdk-reference/knowledge-bases#list)       | `list[KnowledgeBase]` | All KBs accessible to the org. |
| [`aget` / `get`](/developers/sdk-reference/knowledge-bases#get)          | `KnowledgeBase`       | Load one KB by id.             |
| [`acreate` / `create`](/developers/sdk-reference/knowledge-bases#create) | `KnowledgeBase`       | Create a new KB.               |

## `KnowledgeBase` instance methods

See the [`KnowledgeBase` class reference](/developers/sdk-reference/knowledge-bases#knowledgebase-class) for:

* `aadd_documents` / `add_documents`
* `alist_documents` / `list_documents`
* `adelete_multiple_documents` / `delete_multiple_documents`
* `asearch` / `search`
* `adelete` / `delete`

## Linking to an agent

Knowledge bases linked to an agent are configured in the Workbench or with `agent.attach_knowledge_base(...)`. Once linked, the agent's framework retriever queries them automatically: see the [Agent knowledge bases page](/developers/sdk-reference/agents#knowledge-bases).

## create

`KnowledgeBases.acreate` provisions a new managed knowledge base. The returned `KnowledgeBase` is empty until you `aadd_documents(...)` to populate it.

```python theme={"dark"}
from xpander_sdk import KnowledgeBases

kb = await KnowledgeBases().acreate(
    name="Q4 Reports",
    description="Quarterly earnings",
)
print(kb.id, kb.total_documents)   # kb-…, 0
```

#### Parameters

| Parameter     | Type  | Required | Default | Description                         |
| ------------- | ----- | -------- | ------- | ----------------------------------- |
| `name`        | `str` | Yes      | –       | Display name.                       |
| `description` | `str` | No       | `""`    | Description. Useful for cataloging. |

#### Returns `KnowledgeBase`

A new `KnowledgeBase` with `total_documents=0`. Use `kb.aadd_documents([...])` to populate it.

### Examples

#### Create + populate

```python theme={"dark"}
kbs = KnowledgeBases()

kb = await kbs.acreate(
    name="Engineering RFCs",
    description="All historical RFC documents.",
)

await kb.aadd_documents([
    "https://docs.acme.com/rfc/0001-architecture.md",
    "https://docs.acme.com/rfc/0002-deployment.md",
])
```

`aadd_documents` accepts a list of URLs the platform fetches and ingests. See the [`KnowledgeBase` reference](/developers/sdk-reference/knowledge-bases#aadd_documents-/-add_documents).

#### Sync version

```python theme={"dark"}
kb = KnowledgeBases().create(name="My KB", description="...")
```

### Errors

Raises [`ModuleException`](/developers/sdk-reference/overview#error-handling) on failure.

## get

`KnowledgeBases.aget` loads one knowledge base by id, returning a full `KnowledgeBase` instance.

```python theme={"dark"}
from xpander_sdk import KnowledgeBases

kb = await KnowledgeBases().aget(knowledge_base_id="kb-456")
print(kb.name, kb.total_documents)
```

#### Parameters

| Parameter           | Type  | Required | Description |
| ------------------- | ----- | -------- | ----------- |
| `knowledge_base_id` | `str` | Yes      | KB id.      |

#### Returns `KnowledgeBase`

A full `KnowledgeBase` instance. See the [`KnowledgeBase` class reference](/developers/sdk-reference/knowledge-bases#knowledgebase-class).

### Sync version

```python theme={"dark"}
kb = KnowledgeBases().get(knowledge_base_id="kb-456")
```

### Errors

Raises [`ModuleException`](/developers/sdk-reference/overview#error-handling) on failure:

| Status | Cause                           |
| ------ | ------------------------------- |
| 404    | KB doesn't exist or wrong org.  |
| 403    | KB exists but isn't accessible. |
| 500    | Server error.                   |

## list

`KnowledgeBases.alist` returns every knowledge base your organization owns.

```python theme={"dark"}
from xpander_sdk import KnowledgeBases

kbs = await KnowledgeBases().alist()
for kb in kbs:
    print(kb.id, kb.name, kb.total_documents)
```

#### Parameters

None.

#### Returns `list[KnowledgeBase]`

Each `KnowledgeBase` is a full instance. See the [`KnowledgeBase` class reference](/developers/sdk-reference/knowledge-bases#knowledgebase-class) for fields and methods.

| Field             | Type                | Description                                                           |
| ----------------- | ------------------- | --------------------------------------------------------------------- |
| `id`              | `str`               | Knowledge-base identifier.                                            |
| `name`            | `str`               | Display name.                                                         |
| `description`     | `str \| None`       | Description.                                                          |
| `type`            | `KnowledgeBaseType` | `MANAGED` (xpander.ai vector store) or `EXTERNAL` (provider-managed). |
| `organization_id` | `str`               | Owning org.                                                           |
| `total_documents` | `int`               | Document count.                                                       |

### Sync version

```python theme={"dark"}
kbs = KnowledgeBases().list()
```

### Errors

Raises [`ModuleException`](/developers/sdk-reference/overview#error-handling) on failure.

## KnowledgeBase class

`KnowledgeBase` is the instance you get back from `KnowledgeBases.aget`, `acreate`, or `alist`. It carries the KB metadata and the methods to populate, query, and tear it down.

```python theme={"dark"}
from xpander_sdk import KnowledgeBases

kb = await KnowledgeBases().aget("kb-456")
print(kb.id, kb.name, kb.total_documents)
```

### Attributes

| Field             | Type                    | Description                                        |
| ----------------- | ----------------------- | -------------------------------------------------- |
| `id`              | `str`                   | KB identifier.                                     |
| `name`            | `str`                   | Display name.                                      |
| `description`     | `str \| None`           | Description.                                       |
| `type`            | `KnowledgeBaseType`     | `MANAGED` (xpander.ai vector store) or `EXTERNAL`. |
| `organization_id` | `str`                   | Owning org.                                        |
| `total_documents` | `int`                   | Document count.                                    |
| `configuration`   | `Configuration \| None` | SDK config (carried from the loader).              |

### Methods

#### `aadd_documents` / `add_documents`

Upload documents by URL. The platform fetches the URLs, chunks the content, embeds it, and indexes the embeddings.

```python theme={"dark"}
docs = await kb.aadd_documents([
    "https://example.com/policy.pdf",
    "https://example.com/handbook.md",
])
for d in docs:
    print(d.id, d.document_url)
```

| Parameter       | Type        | Required | Default | Description                                                                  |
| --------------- | ----------- | -------- | ------- | ---------------------------------------------------------------------------- |
| `document_urls` | `list[str]` | Yes      | –       | URLs to ingest.                                                              |
| `sync`          | `bool`      | No       | `False` | When `True`, the platform synchronously waits for indexing before returning. |

Returns `list[KnowledgeBaseDocumentItem]`: one entry per uploaded document with the platform-assigned `id` and the `document_url`.

#### `alist_documents` / `list_documents`

List all documents in the KB.

```python theme={"dark"}
docs = await kb.alist_documents()
```

Returns `list[KnowledgeBaseDocumentItem]`.

`KnowledgeBaseDocumentItem` fields:

| Field          | Type          | Description                                   |
| -------------- | ------------- | --------------------------------------------- |
| `kb_id`        | `str \| None` | Owning KB id.                                 |
| `id`           | `str \| None` | Document id.                                  |
| `document_url` | `str`         | URL the platform ingested.                    |
| `raw_data`     | `str \| None` | Inline raw text, if it was uploaded directly. |

#### `adelete_multiple_documents` / `delete_multiple_documents`

Delete documents by id.

```python theme={"dark"}
await kb.adelete_multiple_documents(document_ids=["doc-123", "doc-456"])
```

| Parameter      | Type        | Required | Description             |
| -------------- | ----------- | -------- | ----------------------- |
| `document_ids` | `list[str]` | Yes      | Document ids to delete. |

To delete a single document, you can also call `await doc.delete()` on a `KnowledgeBaseDocumentItem` returned by `alist_documents`.

#### `asearch` / `search`

Semantic search over the KB. Returns top-K matches by score.

```python theme={"dark"}
results = await kb.asearch(
    search_query="how do we handle PII?",
    top_k=5,
)
for r in results:
    print(f"{r.score:.1f}  {r.content[:100]}")
```

| Parameter      | Type   | Required | Default | Description                                                                                                                                                                                                         |
| -------------- | ------ | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `search_query` | `str`  | Yes      | –       | Natural-language query.                                                                                                                                                                                             |
| `use_bubble`   | `bool` | No       | `False` | When `False`, each result is just the matched chunk (the indexed text segment). When `True`, the SDK widens each result with surrounding text from the source document (a "bubble" of context) for richer snippets. |
| `bubble_size`  | `int`  | No       | `1000`  | Width of the surrounding bubble in characters when `use_bubble=True`.                                                                                                                                               |
| `top_k`        | `int`  | No       | `10`    | Max number of results.                                                                                                                                                                                              |

Returns `list[KnowledgeBaseSearchResult]`:

| Field     | Type    | Description                                     |
| --------- | ------- | ----------------------------------------------- |
| `content` | `str`   | Matching text (with bubble context if enabled). |
| `score`   | `float` | Relevance score, 0–100.                         |

#### `adelete` / `delete`

Delete the entire knowledge base.

```python theme={"dark"}
await kb.adelete()
```

This is irreversible. The KB and all its documents are removed.

### Examples

#### Bulk-add and verify

```python theme={"dark"}
docs = await kb.aadd_documents([
    f"https://docs.acme.com/handbook/{slug}.md"
    for slug in ["onboarding", "policies", "engineering"]
])

assert len(docs) == 3
print(f"Added {len(docs)} documents to {kb.name}")
```

#### Search with context

```python theme={"dark"}
results = await kb.asearch(
    search_query="vacation policy",
    use_bubble=True,
    bubble_size=2000,
    top_k=3,
)

for r in results:
    print(f"--- score: {r.score:.1f} ---")
    print(r.content)
```

`use_bubble=True` is great for human-readable snippets; for embedding into LLM prompts, the default `False` (chunk-only) is usually enough.

#### Reindex (delete + re-add)

```python theme={"dark"}
docs = await kb.alist_documents()
ids = [d.id for d in docs]
await kb.adelete_multiple_documents(document_ids=ids)

await kb.aadd_documents([d.document_url for d in docs], sync=True)
```

`sync=True` blocks until reindexing finishes, so the KB is queryable when the call returns.

### Errors

All KB methods raise [`ModuleException`](/developers/sdk-reference/overview#error-handling) on API failures.
