Skip to main content
ExuluContext defines a knowledge collection: a typed schema of fields, an embedding model, chunking, optional data sources and processors, and a hybrid search method that combines pgvector similarity with Postgres full-text search under role-based access control. Contexts you register on ExuluApp appear as Knowledge in the platform UI, where users browse items and agents retrieve from them.

What a context gives you

Typed items

Custom fields on top of built-in columns (name, description, tags, rights mode, external ID).

Hybrid search

Vector similarity, full-text search, or both — with score cutoffs, chunk expansion, and RBAC filtering.

Sources

Scheduled cron ingestion from external systems, upserting by external ID.

Processors

Transform items on insert or update — extract text from files, enrich, then embed.

Entity layer

Optional entity extraction over chunks for graph-style filtering and insights.

Pipelines

Query rewriting, score cutoffs, and chunk expansion around retrieval.

Database layout

Each context owns up to three Postgres tables, named after the context ID (lowercased, spaces replaced by underscores): Built-in item columns include id (UUID), name, description, tags, archived, external_id (unique), created_by, ttl, rights_mode, embeddings_updated_at, last_processed_at, textlength, source, chunks_count, createdAt, updatedAt, and a generated fts column indexing name, description, and external ID. Fields of type file become a <name>_s3key column holding the S3 object key.
The context id becomes the table name — never change it after creation, or the context points at empty tables. IDs must start with a letter or underscore, use only letters, digits, and underscores, and be at most 80 characters; treat 5 as the practical minimum.

Minimal example

Register it on the app:
The embedder.model is the model_name of an embedding model declared in config.litellm.yaml. Embedding generation runs through the LiteLLM proxy, and the chunks table’s vector dimensionality is read from the model’s model_info. There is no separate embedder class — chunking is configured independently via the context’s chunker, defaulting to the built-in sentence chunker. See LiteLLM for model declaration.

Searching

search() is the retrieval entry point. Three methods are supported: Pass a user to enforce access control — only chunks from items the user may read are returned. Score cutoffs, chunk expand windows, and the optional queryRewriter hook shape the result set; the optional entity layer adds entityFilter and entityInsights. All options are covered in the API reference.

Ingesting data

Three ways to get items into a context:
  1. Direct callscreateItem() / updateItem() from your own code, or through the platform’s GraphQL API and UI.
  2. Sources — declare an execute function with a cron schedule; the worker process runs it on schedule and upserts the returned items by external_id.
  3. Processors — transform items on insert or update (for example, extract text from an uploaded PDF) and optionally trigger embedding generation when done.
Embedding generation itself is controlled by configuration.calculateVectors (manual, onInsert, onUpdate, or always) and can run inline or on a BullMQ queue.

Next steps

Configuration

Every constructor option: fields, embedder, chunker, sources, processor, entities.

API reference

Every public method: search, item CRUD, embeddings, entity layer, tables.