Skip to main content

index4ai

Official Python SDK for index4ai: index documents into a project namespace and get prompt-ready retrieval context for RAG from hybrid search.

Installation

Requires Python 3.10+.

pip install index4ai

Authentication

index4ai uses a project API key. Create one in the index4ai console (https://console.index4.ai) and set it in your environment:

export INDEX4AI_API_KEY="..."

or pass api_key= to the client. The client checks the key's prefix when it is created and raises InvalidApiKeyError if you pass a key that is not a project key, so a misconfiguration fails locally instead of as a 401/403.

Usage

from index4ai import Index4AI

client = Index4AI()  # reads INDEX4AI_API_KEY

# 0. List the project's typed attributes BEFORE declaring any.
#    Attribute names (and their types) are permanent per project and capped at
#    `max_names`, so reuse an existing name instead of minting a near-duplicate.
known = {a.name: a.type for a in client.list_attributes().attributes}

# 1. Ingest a document. It is indexed into your project namespace; there is no
#    archive to download. Typed attributes enable query-time filtering:
#    string/int/float/bool are inferred; datetime and encrypted_text must be
#    declared in attribute_schema.
result = client.ingest(
    "document.pdf",
    attributes={"source": "treasury", "published_at": "2023-01-01T00:00:00Z"},
    attribute_schema={"published_at": {"type": "datetime"}},
)
print(result.doc_id, result.status, result.usage)

# 1b. Or let the server fetch the file from a public URL — no upload.
#     Optionally POST a webhook when the job finishes; the value is
#     "<url>|<header>:<value>|..." (capped at 1024 chars).
result = client.ingest(
    remote_url="https://example.com/document.pdf",
    completion="https://example.com/hook|x-api-key:secret",
)

# 2. Hybrid search across all documents in the namespace. Returns a
#    prompt-ready XML+Markdown block — drop it straight into an LLM prompt.
ctx = client.search(
    "How do I configure retries?",
    target_tokens=2048,
    attribute_filters=[{"attr": "source", "op": "eq", "value": "treasury"}],
)
print(ctx.context)

# 3. List, inspect, and delete documents. list_docs() follows pagination and
#    returns every document in the namespace.
for doc in client.list_docs():
    print(doc.doc_id, doc.filename, doc.pages)

deleted = client.delete_doc(result.doc_id)
print(deleted.vectors_deleted, deleted.storage_deleted)

The document id

ingest() / collect() return an IngestResult whose doc_id is the id to search and manage the document by. If the same content was already indexed, the server keeps the existing document instead: deduplicated is True and doc_id is the pre-existing document's id. doc_id is None only when the server reported no indexing outcome.

Submitting and waiting separately

ingest() is submit() followed by collect(). To submit many files and collect later, split them:

job_id = client.submit("document.pdf")
# ... later, even from another process:
result = client.collect(job_id)

Waiting can always be resumed with the same job_id. Submitting the file again instead creates a second job. Two errors tell you which case you are in:

  • JobWaitError — the job exists and keeps running; only the wait failed (network, unreadable status). Resume with client.collect(err.job_id).
  • SubmitUncertainError — the connection failed mid-submit, so the server may or may not have created a job. Check list_docs() before submitting again.

Listing attributes: list before you declare

list_attributes() returns an AttributeList: attributes (a list of AttributeInfo(name, type)), max_names (the project's cap on distinct names) and note (the server's guidance).

Attribute names are permanent per project — the first write of a name fixes its type and spends one of the max_names slots, and clearing a value does not free the name. Call list_attributes() before declaring attributes and reuse an existing name with its existing type.

A 503 means the attribute schema is temporarily unreadable. It is raised as ApiError with status_code == 503 — retry later; never treat it as an empty list, or you will mint duplicate names. A response without an attributes list raises InvalidResponseError for the same reason.

Async

AsyncIndex4AI mirrors the sync client method for method:

import asyncio

from index4ai import AsyncIndex4AI


async def main() -> None:
    async with AsyncIndex4AI() as client:
        ctx = await client.search_in_doc("summarize section 3", "doc_abc123")
        print(ctx.context)


asyncio.run(main())

Migrating from poma.Grill

Before (poma ≤ 0.7) Now (index4ai)
pip install poma pip install index4ai
from poma import Grill, AsyncGrill from index4ai import Index4AI, AsyncIndex4AI
POMA_GRILL_API_KEY INDEX4AI_API_KEY (same project key)
GrillIngestResult (find the doc via list_docs()) IngestResult with doc_id
GrillContext SearchContext
InvalidGrillApiKeyError InvalidApiKeyError
labels / meta_int_*, labels_any… / meta_int_*_gte… attributes / attribute_schema, attribute_filters
return_page_images removed

Configuration

Environment variable Purpose Default
INDEX4AI_API_KEY Project API key — (required)
INDEX4AI_API_BASE_URL API host override https://api.index4.ai

The client targets API version 1 (https://api.index4.ai/v1).

Metadata

Release files for index4ai 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for index4ai 0.1.0
File Size Uploaded
index4ai-0.1.0.tar.gz 33.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for index4ai 0.1.0
File Interpreter ABI Platform
index4ai-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 57.0 kB

Release files / index4ai-0.1.0.tar.gz

Download URL index4ai-0.1.0.tar.gz
Size 33.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e50ad43d36e87e8ff4a9b2d6e3fe2b9431f9e981951ea4d018e1b7f32d2f1d88
BLAKE2b-256 checksum
How to use checksums
4bd25ee99016fade2924dd2fdda8e2ff3a01e03fea95a918e79fdf776e7717b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.

Transparency log

Release files / index4ai-0.1.0-py3-none-any.whl

Download URL index4ai-0.1.0-py3-none-any.whl
Size 23.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a2309b2ee4fed97cc73b5a78956c546ab67ea4d72893ad857601e22c6e00e3d8
BLAKE2b-256 checksum
How to use checksums
61f40eb96564f676ec59eed23fd75be1da3b870f111ace202dcb2178495bdc40
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page