Files
lancedb/.agents/skills/lancedb/references/python/api_reference.md
T
Dan Tasse 00c4a7b843 chore: consolidate skills into one (#3672)
Consolidating skills so we have only one `lancedb` skill, making it
easier to install and work with, vs. installing and using different
skills for "lancedb-column-metadata", "lancedb-branch-ops", etc.

Also deleted lancedb-connect, because the new monoskill uses the
python/TS APIs so it doesn't need extra handholding to connect to the
REST API.

## does it work?

Test 1: do some column metadata operations with 1. no skills, 2. our
previous baseline lancedb skill, 3. the baseline lancedb skill with the
lancedb-column-metadata skill folded in:

```
┌───────────────────────────┬──────────────────────┬────────────────────┬───────────────────────┐
│           eval            │       no-skill       │ lancedb (original) │ lancedb2-incl-columns │
├───────────────────────────┼──────────────────────┼────────────────────┼───────────────────────┤
│ 2-add-all-metadata-types  │ 2.5/5 · 116s · $0.44 │ 0/5 · 154s · $0.60 │ 5/5 · 58s · $0.26     │
├───────────────────────────┼──────────────────────┼────────────────────┼───────────────────────┤
│ 3-delete-one-metadata-key │ 4/4 · 67s · $0.23    │ 4/4 · 100s · $0.45 │ 4/4 · 45s · $0.20     │
├───────────────────────────┼──────────────────────┼────────────────────┼───────────────────────┤
│ TOTAL (per rep avg)       │ 6.5/9 · 183s · $0.66 │ 4/9 · 254s · $1.05 │ 9/9 · 103s · $0.46    │
└───────────────────────────┴──────────────────────┴────────────────────┴───────────────────────┘
```
without column-metadata-specific content, it failed because it wrote
keys like `description` instead of `lancedb:description`. That's pretty
undiscoverable without the skill.


Test 2: do some simple branch operations with 1. no skills, 2. our
previous baseline lancedb skill, 3. the combined skill (in this PR):
```
┌───────────────────────────┬────────────────────┬────────────────────┬────────────────────────────────┐
│           eval            │      no-skill      │ lancedb (original) │ lancedb3-incl-columns-branches │
├───────────────────────────┼────────────────────┼────────────────────┼────────────────────────────────┤
│ 5-create-branch           │ 2/2 · 64s · $0.30  │ 2/2 · 57s · $0.34  │ 2/2 · 38s · $0.22              │
├───────────────────────────┼────────────────────┼────────────────────┼────────────────────────────────┤
│ 6-delete-branch           │ 2/2 · 38s · $0.21  │ 2/2 · 44s · $0.27  │ 2/2 · 40s · $0.22              │
├───────────────────────────┼────────────────────┼────────────────────┼────────────────────────────────┤
│ 7-switch-branch-and-write │ 1/2 · 96s · $0.49  │ 1/2 · 106s · $0.58 │ 2/2 · 66s · $0.40              │
├───────────────────────────┼────────────────────┼────────────────────┼────────────────────────────────┤
│ TOTAL (per rep avg)       │ 5/6 · 199s · $1.00 │ 5/6 · 207s · $1.20 │ 6/6 · 143s · $0.83             │
└───────────────────────────┴────────────────────┴────────────────────┴────────────────────────────────┘
```

Test 3: run everything, with the lancedb (original) skill,
lancedb(original) + all the separate skills, and
lancedb3-incl-columns-branches
```
┌────────────────────────────────┬──────────────────────┬────────────────────────────────┬─────────────────────────────────────────────────────────────────┐
│              eval              │  lancedb (original)  │ lancedb3-incl-columns-branches │ all-separate (lancedb + connect + column-metadata + branch-ops) │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 1-pick-column-for-image-search │ 2/2 · 141s · $0.67   │ 2/2 · 128s · $0.43             │ 1/2 · 257s · $0.81                                              │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 2-add-all-metadata-types       │ 5/5 · 93s · $0.52    │ 5/5 · 54s · $0.30              │ 5/5 · 40s · $0.24                                               │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 3-delete-one-metadata-key      │ 4/4 · 84s · $0.44    │ 4/4 · 36s · $0.24              │ 4/4 · 28s · $0.20                                               │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 4-build-index                  │ 3/3 · 275s · $0.52   │ 3/3 · 84s · $0.39              │ 3/3 · 68s · $0.50                                               │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 5-create-branch                │ 2/2 · 39s · $0.31    │ 2/2 · 41s · $0.20              │ 2/2 · 15s · $0.17                                               │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 6-delete-branch                │ 2/2 · 59s · $0.25    │ 2/2 · 69s · $0.29              │ 2/2 · 26s · $0.17                                               │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ 7-switch-branch-and-write      │ 1/2 · 84s · $0.46    │ 2/2 · 62s · $0.40              │ 2/2 · 27s · $0.23                                               │
├────────────────────────────────┼──────────────────────┼────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ TOTAL                          │ 19/20 · 774s · $3.17 │ 20/20 · 474s · $2.24           │ 19/20 · 462s · $2.32                                            │
└────────────────────────────────┴──────────────────────┴────────────────────────────────┴─────────────────────────────────────────────────────────────────┘
```

("lancedb3-incl-columns-branches" is the combined skill in this PR,
all-separate is using the four separate skills.)

For overall performance, it helps to have the specialized skills for
metadata and branching; doesn't really matter whether they're separate
skills or all together. Also doesn't matter much whether it's REST or
Python. So let's merge these skills to make it easier for users.
2026-07-15 16:54:23 -04:00

6.2 KiB

Python API Reference

Quick method reference for Python LanceDB code. Cross-check source for non-trivial claims.

Connect

import lancedb

db = lancedb.connect("./camelot-db")         # local/OSS
db = lancedb.connect("db://my-db", api_key=api_key, region=region)  # remote

Place the local database directory next to the script/entrypoint that opens it (i.e. resolve the path relative to the script, Path(__file__).parent / "camelot-db"), not buried under a shared data/ folder. The Lance dataset is the database, not a data file — keeping it beside its code makes ownership obvious and paths stable regardless of the working directory the script is launched from.

Do not name the directory lancedb (e.g. ./lancedb, ./data/lancedb). It collides with the imported lancedb package name, which is confusing to read and easy to shadow in scripts. Give it a name derived from the repo or dataset with a clear prefix/suffix — for example ./<dataset>-db, ./<repo>_lancedb, or ./vectordb.

Async:

db = await lancedb.connect_async("./camelot-db")

Table Reads

Task Preferred API
Vector search table.search(query_vector).limit(k)
Full scan with filters/projection (sync) table.search().where(...).select(...).limit(...)
Full scan with filters/projection (async) table.query().where(...).select(...).limit(...)
Filter .where("col > 10")
Projection .select(["id", "text"])
Bound result count .limit(20)
Collect bounded result as Python objects (default, no extra deps) .to_list() on query/search result
Collect bounded result as Arrow (default, pyarrow always available) .to_arrow() on query/search result
Collect bounded result as pandas (only if project uses pandas) .to_pandas() on query/search result
Collect bounded result as Polars (only if project uses polars) .to_polars() on query/search result

Sync vs Async Scan API

The plain-scan entry point differs between the sync and async clients. Verified against lancedb 0.34.0 — re-check if the pinned version changes:

  • Sync (lancedb.connect(...)): the table has no .query() method. Use .search() with no argument for a plain scan; it returns a query builder that supports .where(), .select(), .limit(), and the .to_list() / .to_arrow() / .to_pandas() / .to_polars() collectors.
    rows = table.search().where("status = 'ready'").select(["id", "text"]).limit(20).to_list()
    
  • Async (lancedb.connect_async(...)): the table has both .query() and .search(). Use .query() for a plain scan.
    rows = await async_table.query().where("status = 'ready'").select(["id", "text"]).limit(20).to_list()
    

Do not call table.query() on a sync table — it raises AttributeError.

Local vs Remote Table Methods

API Local table Remote table Agent guidance
table.search(...) Yes Yes Preferred read path (sync + async)
table.query() Async only Async only Sync scan path is table.search(); .query() is the async scan builder
table.to_pandas() Yes No / unsafe for portability Avoid in portable code
table.to_arrow() Yes No / unsafe for portability Avoid in portable code
table.to_polars() Yes No / unsafe for portability Avoid in portable code
table.to_lance() Yes No Local/OSS escape hatch only

Indexes

Use create_index(...) for vector indexes and modern index configs. Use scalar indexes for filtered or merge keys.

Common calls:

table.create_index("vector")
table.create_scalar_index("status")
table.create_fts_index("text")

Check source docs before specifying advanced index config names or parameters.

Filtering And Recall Knobs

table.search(query_vector).where("status = 'ready'")  # pre-filter by default
table.search(query_vector).where("status = 'ready'", prefilter=False)
table.search(query_vector).limit(10).refine_factor(20)
table.search(query_vector).limit(10).nprobes(50)

Use post-filtering only when fewer than limit results are acceptable.

Diagnostics

print(table.search(query_vector).where("year > 2000").limit(10).analyze_plan())
print(table.index_stats("vector_idx"))

Use these before changing indexes or search tuning.

Column (Field) Metadata

schema = table.schema                       # sync property; async: await table.schema()
meta = schema.field("category").metadata    # dict[bytes, bytes] — Arrow metadata is bytes-keyed
res = table.update_field_metadata(          # varargs: one dict per field; works local + remote
    {"path": "category", "metadata": {"lancedb:description": "...", "lancedb:tag:field_type": "label"}}
)
res.version  # new table version

Merges by default; a None value deletes that key; "replace": True swaps the whole map. Nested fields use dot-paths ("a.b.c"). replace_field_metadata is deprecated. See references/column_metadata.md for key conventions (lancedb:description, lancedb:tag:<name>, lancedb:logical-column) and the authoring workflow.

Branches

table.branches.list()                          # non-main branches; {} = only main
exp = table.branches.create("exp")             # fork off main -> handle scoped to the branch
wip = table.branches.checkout("wip")           # existing branch -> scoped handle (version= pins read-only)
wip = db.open_table("t", branch="wip")         # or open scoped directly
table.branches.delete("stale")                 # removes only the branch pointer
table.current_branch()                         # None = main

There is no global switch — scoping is per table handle: any read/write on a branch handle lands on that branch; the original handle keeps targeting main. See references/branch_ops.md for the model and isolation checks.

Maintenance

table.optimize()

Call this after every successful local/OSS ingestion. It handles compaction, cleanup of old versions according to retention, and index optimization. Do not add this for LanceDB Enterprise/Cloud remote tables; Enterprise handles compaction and cleanup automatically from cluster configuration.