Library / SDK
pinecone-io/python-sdk avatar
pinecone-io/python-sdk

Pinecone Python SDK: schema-based indexes, three data-plane interfaces, and the v10 break

Official Python SDK for the Pinecone vector database

452 stars133 forksPythonApache-2.0

At a glance

What is it?
The official Python client for Pinecone's vector database moved index creation to a schema/deployment model in v10.0.0, and which of three data-plane interfaces you get depends on how the index was created.
Who is it for?
Adopt the Pinecone Python SDK if you are building Python retrieval or RAG workloads on Pinecone's managed service and want one client that covers index management, document upsert and search, and async IO. Do not adopt it if you need a self-hosted or embedded vector store, or if you are pinned to Python below 3.10, since requires-python is >=3.10.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 11 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: one client for index management and document search

Pinecone is a hosted vector database, so a Python application needs two different things from a client library: control-plane calls that create and configure indexes, and data-plane calls that write and read records. The Pinecone Python SDK packages both behind one import. The README describes it as a client to "create and manage indexes, upsert and query records, and run inference operations from Python."

The intended audience is narrow but real. It is for engineers building retrieval or RAG pipelines who have already chosen Pinecone as the store and now need the Python side to be correct: connection handling, timeouts, async IO, retries. It is not a general vector library. There is no local index, no in-process fallback, and the README never suggests one. If you want to prototype without a hosted service, this SDK gives you nothing to run against.

The package has been stable for a while by its own metadata. pyproject.toml carries the classifier "Development Status :: 5 - Production/Stable", and the version at the time of writing is 10.0.0.

How the v10 schema and deployment model changes index creation

The largest structural fact in the README is a breaking change. Upgrading from 9.x, the arguments `create` and `configure` take moved from `spec=` and `dimension=` to `schema=` and `deployment=`. The README links a v10 migration guide at sdk.pinecone.io/python/migration/v10-migration.html with a field-by-field mapping. If you are on 9.x and have index-creation code checked in, that mapping is the first thing to read, because the old keyword arguments are gone rather than deprecated in place.

The new model is worth understanding on its own terms. An index declares its fields as a schema, and the README states that declaring a schema makes it a document index. You then read and write through `index.documents`, and each record is a JSON document whose fields you named yourself. In the quick-start example the schema declares a single field called `embedding` with `type` of `dense_vector`, `dimension` 3, and `metric` `cosine`. Other keys in an upserted document are either declared schema fields or arbitrary metadata, and every document needs an `_id`.

Search follows the same shape. `index.documents.search` takes `top_k`, a `score_by` list naming the field to compare against, and `include_fields` to control what comes back. The example wraps the field in a `DenseVectorQuery` object rather than passing a bare vector, so the query surface is structured rather than a keyword argument on the method.

Three data-plane interfaces, chosen by how the index was created

This is the part of the design most likely to confuse a new user, and the README addresses it directly. Three data-plane interfaces exist, and the way the index was created decides which one applies.

An index created with the deprecated top-level vector arguments answers on `index.upsert` and `index.query`. An index created with `pc.indexes.create_for_model(...)` embeds text server-side and answers on `index.upsert_records` and `index.search`. A document index, created with a schema as in the quick start, answers on `index.documents.upsert` and `index.documents.search`.

The trade-off is explicit in the naming: you cannot call the same method on every index. Code that works against one index type will fail against another, and the failure is a method that does not exist on the handle rather than a clear type error. When you move an application between index types, the call sites change, not just the arguments. The README points to the quickstart and the wider documentation for the full picture, which is a fair signal that the three-interface split is documented in more depth than the repository front page carries.

Installing the Pinecone Python SDK and running a first search

The README gives a single install command and requires Python 3.10 or newer, which pyproject.toml confirms with `requires-python = ">=3.10"`. The package is built with maturin, so the wheel is produced by a Rust build backend; the repository contains a Cargo workspace with a `rust` member alongside the `pinecone/` Python package.

bash
pip install pinecone

After installing, you need an API key. You can pass it explicitly or set the `PINECONE_API_KEY` environment variable and construct the client with no arguments. The README shows both forms.

python
from pinecone import Pinecone

pc = Pinecone(api_key="your-api-key")
# or, with PINECONE_API_KEY set in the environment:
pc = Pinecone()

Creating an index blocks until the index is ready, per the README comment in the quick-start block. The example builds a three-dimensional cosine index on a managed deployment in AWS us-east-1, then opens a data-plane handle with `pc.index(...)`.

python
from pinecone import DenseVectorQuery, Pinecone

pc = Pinecone(api_key="your-api-key")
pc.indexes.create(
    name="movie-recommendations",
    schema={"fields": {"embedding": {"type": "dense_vector", "dimension": 3, "metric": "cosine"}}},
    deployment={"deployment_type": "managed", "cloud": "aws", "region": "us-east-1"},
)
index = pc.index("movie-recommendations")

Upserting and searching go through `index.documents`. Each document carries an `_id`, and `include_fields` limits what the search returns. The loop below prints the id and score of each match, which is what the README example does.

python
index.documents.upsert(
    namespace="movies-en",
    documents=[
        {"_id": "movie-001", "embedding": [0.1, 0.2, 0.3], "title": "Arrival"},
        {"_id": "movie-002", "embedding": [0.4, 0.5, 0.6], "title": "Interstellar"},
    ],
)

results = index.documents.search(
    namespace="movies-en",
    top_k=5,
    score_by=[DenseVectorQuery(field="embedding", values=[0.1, 0.2, 0.3])],
    include_fields=["title"],
)
for doc in results.matches:
    print(doc.id, doc.score)

One behaviour will catch people out on the first run. The README states that upserts apply asynchronously, so a document may not be visible to the next search immediately. A script that upserts and then immediately searches for the same record can return nothing, and that is expected rather than a bug in your code.

Async, timeouts, and custom hosts for production use

The SDK ships an async client for asyncio. The shape differs from the sync client in two ways the README calls out: `index()` on the async client is a coroutine, and the handle it returns is a context manager. So you await the handle and then enter it with `async with` before issuing queries.

python
import asyncio
from pinecone import AsyncPinecone, DenseVectorQuery

async def main():
    async with AsyncPinecone(api_key="your-api-key") as pc:
        index = await pc.index("movie-recommendations")
        async with index:
            results = await index.documents.search(
                namespace="movies-en",
                top_k=5,
                score_by=[DenseVectorQuery(field="embedding", values=[0.1, 0.2, 0.3])],
                include_fields=["title"],
            )

asyncio.run(main())

Configuration beyond the API key is small and documented. `host=` points the client at a specific control plane host, with `https://api.pinecone.io` as the example value. `timeout=` sets request timeouts in seconds, and the README example uses 30. Debug logging is switched on with the `PINECONE_DEBUG` environment variable set to 1, not with a constructor argument. There is also a `PINECONE_ADDITIONAL_HEADERS` variable in .env.example, documented as a JSON string of extra headers attached to every request, with the example `{"x-my-trace-id": "abc-123"}`. That file is framed around integration testing, so treat it as the place those variables are demonstrated rather than as a full configuration reference.

Where the SDK is the wrong tool, and what the retry smoke tests cost

The clearest limitation is that this is a client for a hosted service. There is no offline mode, no local persistence, and no way to run the quick start without an API key and a reachable Pinecone deployment. For unit tests, that means you mock the client, and the repository's own test layout reflects the split: `tests/unit/` runs without a backend, while `tests/integration/` hits a real one.

The README is unusually direct about the cost of the opt-in suites. The live retry and throttle smoke tests in `tests/integration/test_retry_smoke.py` need `PINECONE_API_KEY` plus `PINECONE_RETRY_SMOKE=1`, and the README says they hit a real backend and cost money. It also says to run them before any release that touches retry logic, HTTP transport, the AIMD adaptive-concurrency limiter, or the batch-upsert path. That is a real operational constraint on anyone maintaining a fork or contributing: some correctness checks are not free and not run by default.

The other boundary is the version cut. Python 3.10 is the floor, so applications on 3.9 cannot use this release at all. And because v10 changed the index-creation arguments, an upgrade is not a drop-in: `spec=` and `dimension=` no longer apply, and the migration guide is the only mapping the README offers. If your code creates indexes in more than one place, budget for touching each of them.

How this differs from a general-purpose vector library

The natural alternative for a Python team is a library that runs the index inside your own process or your own infrastructure, such as FAISS for in-process similarity search or a self-hosted vector database like Qdrant or Weaviate. The difference is not a feature checklist, it is where the index lives and who operates it.

With an in-process library, you own persistence, replication, shard rebalancing, and the memory budget, and you get to run everything in a unit test with no network. With this SDK, the index is managed, the deployment is declared as a `deployment` dict naming a cloud and region, and the client's job is to talk to it. You give up local testability and gain not having to run the store.

A second axis is the interface model. This SDK's three data-plane interfaces, chosen by how the index was created, are more rigid than a library that exposes one search function. The rigidity buys server-side embedding for `create_for_model` indexes and typed document fields for schema-based ones. If your workload is pure vector similarity with no server-side embedding and no named metadata fields, the document-index path adds a layer you may not need. If you do want text embedded server-side, the alternative libraries generally make you produce the vectors yourself.

Licence, maintenance, and the upgrade cost of v10

The SDK is Apache-2.0, stated in both the README and pyproject.toml, with the full text in the repository LICENSE file. Apache-2.0 is a permissive licence that includes an explicit patent grant, which matters for a client library that may end up inside a commercial product. It is not a copyleft licence, so it does not force you to publish your own code. That is a description of the licence text, not legal advice; if your organisation has a licence review process, the LICENSE file is the document to hand it.

The repository is not archived, and the last push was on 2026-09-04, which is recent enough that the codebase is being touched. The release cadence visible in the data is not fast: v9.0.1 on 2026-05-19, v9.1.0 on 2026-06-04, and v10.0.0 on 2026-09-03. Two of those three are minor or patch releases. The jump to 10.0.0 is the one that carries the breaking index-creation change, so the upgrade cost is concentrated in that step rather than spread across every release.

For a team already on 9.x, the practical upgrade work is mechanical but not zero: find every `pc.indexes.create` and `configure` call, map `spec=` and `dimension=` to `schema=` and `deployment=` using the migration guide, and confirm which data-plane methods each index answers on. The README does not document a rollback path for the change, so plan the migration as a forward move.

Editorial conclusion

Adopt the Pinecone Python SDK if you are building Python retrieval or RAG workloads on Pinecone's managed service and want one client that covers index management, document upsert and search, and async IO. Do not adopt it if you need a self-hosted or embedded vector store, or if you are pinned to Python below 3.10, since requires-python is >=3.10. Before you commit, verify three things against your own code: whether you are on 9.x and therefore need the v10 migration guide, which data-plane interface your existing indexes answer on, and whether your retry or batch-upsert code paths are covered by the opt-in smoke tests in tests/integration/test_retry_smoke.py, which the README says to run before any release that touches retry logic or the batch-upsert path.

Frequently asked questions

How do I install the Pinecone Python SDK?

Install it with pip install pinecone. It requires Python 3.10 or newer, as stated in the README and in pyproject.toml's requires-python field.

What is the difference between the Pinecone Python SDK and the Pinecone API?

The SDK is the Python client that calls the hosted Pinecone vector database; the README describes it as a client for creating and managing indexes, upserting and querying records, and running inference operations. The API itself is the service the client talks to, and the SDK lets you point at a specific control plane host with the host argument.

What changed in Pinecone Python SDK v10.0.0?

Index creation moved from spec= and dimension= to schema= and deployment=. The README links a v10 migration guide with a field-by-field mapping for code upgrading from 9.x.

Which method do I call to search a Pinecone index from Python?

It depends on how the index was created. A schema-based document index answers on index.documents.search, an index created with create_for_model answers on index.search, and an index created with the deprecated top-level vector arguments answers on index.query.

How do I set the Pinecone API key in the Python SDK?

Pass it to the constructor as Pinecone(api_key="your-api-key"), or omit the argument and set the PINECONE_API_KEY environment variable, in which case Pinecone() picks it up.

Official sources

  1. License: Apache-2.0
  2. pinecone-io/python-sdk on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pinecone-io-python-sdk.svg)](https://hysenlabs.com/projects/pinecone-io-python-sdk)