Skip to main content

SDK for building custom Glean indexing integrations

Project description

Glean Indexing SDK

Prerelease PyPI version

A Python SDK for building custom Glean indexing connectors. Provides base classes and utilities to create connectors that fetch data from external systems and upload to Glean's indexing APIs.

Requirements

Installation

pip install glean-indexing-sdk

Key Concepts

Every connector has two parts:

  1. DataClient — fetches raw data from your external system (API, database, files)
  2. Connector — transforms that data into Glean's format and uploads it

The workflow is: fetch → transform → upload. You implement get_source_data() on your data client and transform() on your connector; the SDK handles batching and upload.

See Architecture overview for a data flow diagram and the full class hierarchy.

Quickstart

1. Set up credentials

export GLEAN_SERVER_URL="https://your-company-be.glean.com"
export GLEAN_INDEXING_API_TOKEN="your-indexing-api-token"

# Deprecated alternative: use GLEAN_INSTANCE as legacy fallback
# export GLEAN_INSTANCE="acme"

2. Build a connector

This complete example defines a data type, a data client, and a connector, then indexes everything into Glean:

from typing import List, Sequence, TypedDict

from glean.indexing.connectors import BaseConnectorDataClient, BaseDatasourceConnector
from glean.indexing.models import (
    ContentDefinition,
    CustomDatasourceConfig,
    DocumentDefinition,
    IndexingMode,
    UserReferenceDefinition,
)


class WikiPageData(TypedDict):
    id: str
    title: str
    content: str
    author: str
    created_at: str
    updated_at: str
    url: str
    tags: List[str]


class WikiDataClient(BaseConnectorDataClient[WikiPageData]):
    def __init__(self, wiki_base_url: str, api_token: str):
        self.wiki_base_url = wiki_base_url
        self.api_token = api_token

    def get_source_data(self, since=None) -> Sequence[WikiPageData]:
        # Example static data
        return [
            {
                "id": "page_123",
                "title": "Engineering Onboarding Guide",
                "content": "Welcome to the engineering team...",
                "author": "jane.smith@company.com",
                "created_at": "2024-01-15T10:00:00Z",
                "updated_at": "2024-02-01T14:30:00Z",
                "url": f"{self.wiki_base_url}/pages/123",
                "tags": ["onboarding", "engineering"],
            },
            {
                "id": "page_124",
                "title": "API Documentation Standards",
                "content": "Our standards for API documentation...",
                "author": "john.doe@company.com",
                "created_at": "2024-01-20T09:15:00Z",
                "updated_at": "2024-01-25T16:45:00Z",
                "url": f"{self.wiki_base_url}/pages/124",
                "tags": ["api", "documentation", "standards"],
            },
        ]


class CompanyWikiConnector(BaseDatasourceConnector[WikiPageData]):
    configuration: CustomDatasourceConfig = CustomDatasourceConfig(
        name="company_wiki",
        display_name="Company Wiki",
        url_regex=r"https://wiki\.company\.com/.*",
        trust_url_regex_for_view_activity=True,
        is_user_referenced_by_email=True,
    )

    def transform(self, data: Sequence[WikiPageData]) -> List[DocumentDefinition]:
        documents = []
        for page in data:
            documents.append(
                DocumentDefinition(
                    id=page["id"],
                    title=page["title"],
                    datasource=self.name,
                    view_url=page["url"],
                    body=ContentDefinition(mime_type="text/plain", text_content=page["content"]),
                    author=UserReferenceDefinition(email=page["author"]),
                    created_at=self._parse_timestamp(page["created_at"]),
                    updated_at=self._parse_timestamp(page["updated_at"]),
                    tags=page["tags"],
                )
            )
        return documents

    def _parse_timestamp(self, timestamp_str: str) -> int:
        from datetime import datetime

        dt = datetime.fromisoformat(timestamp_str.replace("Z", "+00:00"))
        return int(dt.timestamp())


data_client = WikiDataClient(wiki_base_url="https://wiki.company.com", api_token="your-wiki-token")
connector = CompanyWikiConnector(name="company_wiki", data_client=data_client)
connector.configure_datasource()
connector.index_data(mode=IndexingMode.FULL)

Connector Types

Connector Data Client Best For
BaseDatasourceConnector BaseDataClient Small-to-medium datasets that fit in memory. Wikis, knowledge bases, file systems.
BaseStreamingDatasourceConnector BaseStreamingDataClient Large or paginated datasets where you need to limit memory usage. Uses sync generators.
BaseAsyncStreamingDatasourceConnector BaseAsyncStreamingDataClient Large datasets with async APIs (aiohttp, httpx async). Non-blocking I/O.
BasePeopleConnector Employee and identity data indexing.

For detailed guidance on choosing between these, see the decision matrix.

Indexing Modes

  • IndexingMode.FULL — Re-indexes all documents. Use for initial loads or when you need a complete refresh.
  • IndexingMode.INCREMENTAL — Only indexes documents modified since the last crawl. Use for scheduled updates to minimize API calls.
connector.index_data(mode=IndexingMode.FULL)         # full re-index
connector.index_data(mode=IndexingMode.INCREMENTAL)   # only changes since last run

Testing

The SDK includes a ConnectorTestHarness that lets you validate your connector without making real API calls. It intercepts uploads and captures the documents your connector produces so you can assert on them.

from glean.indexing.connectors import ConnectorTestHarness

harness = ConnectorTestHarness(connector)
harness.run()

validator = harness.get_validator()
validator.assert_documents_posted(count=2)

# Inspect individual documents
for doc in validator.documents_posted:
    print(doc.title)

Contributing

This project uses mise for toolchain management and uv for Python dependencies.

mise run setup              # create venv and install dependencies
mise run test               # run all tests
mise run lint               # run all linters (ruff, pyright, markdown-code)
mise run lint:fix           # auto-fix lint issues and format code

Next Steps

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

glean_indexing_sdk-1.0.0b2.tar.gz (137.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

glean_indexing_sdk-1.0.0b2-py3-none-any.whl (53.0 kB view details)

Uploaded Python 3

File details

Details for the file glean_indexing_sdk-1.0.0b2.tar.gz.

File metadata

  • Download URL: glean_indexing_sdk-1.0.0b2.tar.gz
  • Upload date:
  • Size: 137.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for glean_indexing_sdk-1.0.0b2.tar.gz
Algorithm Hash digest
SHA256 8f6e1d6fddf373ac034880ac6ce125931fd6fa5c595d7905266dfaf2aacb1c45
MD5 f5164fdba6c51ea7e1193757911b62be
BLAKE2b-256 d09e2ad25fbde5b8b43bdfdf848561a1bf635695cb7d02f8a03f32a917abb743

See more details on using hashes here.

Provenance

The following attestation bundles were made for glean_indexing_sdk-1.0.0b2.tar.gz:

Publisher: publish.yml on gleanwork/glean-indexing-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file glean_indexing_sdk-1.0.0b2-py3-none-any.whl.

File metadata

File hashes

Hashes for glean_indexing_sdk-1.0.0b2-py3-none-any.whl
Algorithm Hash digest
SHA256 0e4a816a5431b8cc738bc40dea11ea50e7a9e4ffadc09be0c1e0c021db17db4f
MD5 47dc42e960708736eac5820caacc8a46
BLAKE2b-256 cb7a694df19c21a2f2925f807e360ef42d5e73a546a59650879b5cf48bd89b6b

See more details on using hashes here.

Provenance

The following attestation bundles were made for glean_indexing_sdk-1.0.0b2-py3-none-any.whl:

Publisher: publish.yml on gleanwork/glean-indexing-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page