Skip to main content
A data source is an external system a Knowledge Base ingests files from. A plugin data source lets you feed documents from a proprietary system, internal store, or niche SaaS into the KB pipeline. The platform owns the KB itself — chunking, embedding, retrieval — and your data source only answers one question: which files should be added?
A data source’s fetch() runs inside the plugin’s sandbox worker, invoked over JSON-RPC (datasource.fetch). Read How plugins run for the execution model — network posture, logging, and especially the file callbacks that move bytes across the sandbox boundary.

The interface

A data source subclasses BaseDataSource[ConfigType] and implements fetch.

Class attributes

ConfigType is your DatasourceConfiguration subclass (a NodeConfiguration, so fields are Parameter(...) with optional display= widgets). It reaches your instance as self.config.

fetch contract

fetch performs a one-shot ingestion: pull the files you want in the KB and return them as File descriptors. This is the “Add knowledge” flow — the user picks your data source, fills its config, and the platform ingests whatever fetch returns. The important rule: you don’t return bytes, you upload them. Fetch each file’s content, then persist it with the file helper:
upload_file stores the bytes on the platform (over a host callback — the sandbox has no direct storage access) and returns a File descriptor. Return the list of descriptors; the platform then chunks and embeds them into the KB. The upload is workspace-scoped by the host, so pass ctx.group_id for the calling workspace. Raise from fetch to fail the ingestion with a user-visible message.

Using credentials

Most data sources talk to an authenticated system. Declare the credential type and read it in fetch:
The credential type comes from a BaseIntegration / BaseCredentials pair in the same plugin — see Creating integrations.

Registering the data source

Return your data source classes from the plugin’s datasources() method:
A plugin that provides a data source satisfies the “at least one node, integration, or data source” requirement on its own. Each data source is serialized into the manifest (DatasourceDefinition); regenerate manifest.json whenever its name or config changes. On the platform side a single generic Plugin Datasource node backs every plugin-provided data source and slots into the existing KB ingestion path — there’s nothing extra to wire; the platform resolves your data source by name from the manifest and dispatches datasource.fetch to the worker.

Sync model

Only one-shot fetch is supported today. Incremental sync — where the platform’s sync engine periodically polls the source for changes and adds/updates/removes documents (a list/get/download interface) — is a later phase. supports_sync is the reserved flag for it; leave it False. Until then, re-running “Add knowledge” is how content is refreshed.

Testing

Unit-test fetch directly with a stubbed file helper, and exercise the full ingestion end to end by installing the plugin against a running stack (the reference plugin under tests/plugins/ includes a data source and its run_plugin_e2e.py driver ingests from it). noxus plugin serve also mirrors datasource.fetch for local development.

How plugins run

The sandbox model and the file callbacks fetch relies on.

Working with files

The File model and the file helper in depth.