Constructor parameters
The ExuluContext constructor accepts a configuration object with the following parameters:
const context = new ExuluContext ({
id: string ,
name: string ,
description: string ,
active: boolean ,
fields: ExuluContextFieldDefinition [],
embedder? : ExuluEmbedder ,
processor? : ExuluContextProcessor ,
sources: ExuluContextSource [],
rateLimit? : RateLimiterRule ,
queryRewriter? : ( query : string ) => Promise < string > ,
resultReranker? : ( results : any []) => Promise < any [] > ,
configuration? : { /* ... */ }
});
Required parameters
Unique identifier for the context. Must be a valid PostgreSQL identifier: start with a letter or underscore, contain only letters, digits, or underscores, 5-80 characters long.
The ID is used for database table names and should not change after creation. Changing the ID requires database migration.
Human-readable name displayed in UI and logs
name : "Product Documentation"
description
Description of what information this context contains. Used in the auto-generated tool description for agents.
description : "Product documentation, help articles, and tutorials for end users"
Whether this context is active and available for use
fields
ExuluContextFieldDefinition[]
required
Array of field definitions that define the schema for items in this context
fields : [
{
name: "title" ,
type: "text" ,
required: true ,
editable: true
},
{
name: "content" ,
type: "text" ,
required: true
},
{
name: "category" ,
type: "text" ,
index: true ,
enumValues: [ "guide" , "reference" , "tutorial" ]
}
]
Field definition properties
Field name (must be valid PostgreSQL column name)
Field type: text, number, boolean, date, json, file, longtext, decimal, integer, timestamp
Whether this field is required when creating items
Whether this field can be edited after creation
Whether this field must have unique values
Whether to create a database index on this field for faster queries
Default value for this field
Whether this field is calculated/computed rather than user-provided
For text fields, restrict values to this list of allowed values
fields[].allowedFileTypes
For file fields, restrict allowed file types (e.g., ["pdf", "docx", "txt"])
sources
sources
ExuluContextSource[]
required
Array of data sources that populate this context
sources : [
{
id: "github_issues" ,
name: "GitHub Issues" ,
description: "Syncs issues from GitHub repository" ,
config: {
schedule: "0 */6 * * *" , // Every 6 hours
queue: await ExuluQueues . register ( "github_sync" ),
retries: 3 ,
backoff: {
type: "exponential" ,
delay: 2000
}
},
execute : async ({ exuluConfig }) => {
const issues = await fetchGitHubIssues ();
return issues . map ( issue => ({
external_id: issue . id ,
name: issue . title ,
content: issue . body ,
metadata: { labels: issue . labels }
}));
}
}
]
Source configuration
Unique identifier for the source
Human-readable source name
Description of what this source provides
sources[].config.schedule
Cron expression for scheduled execution (e.g., "0 * * * *" for hourly)
sources[].config.queue
Promise<ExuluQueueConfig>
Queue configuration for background processing
Number of retry attempts on failure (default: 3)
Backoff strategy for retries: { type: "exponential" | "linear", delay: number }
Async function that fetches and returns items from the source
Optional parameters
embedder
Embedder instance that generates vector embeddings for items
import { ExuluEmbedder } from "@exulu/backend" ;
embedder : new ExuluEmbedder ({
id: "openai_embedder" ,
name: "OpenAI Embeddings" ,
provider: "openai" ,
model: "text-embedding-3-small" ,
vectorDimensions: 1536 ,
template: "{{title}} \n\n {{content}}"
})
Without an embedder, semantic search is not available. You can still use the context for structured data storage and retrieval.
processor
Processor that transforms items before storage or embeddings generation
processor : {
name : "PDF Text Extractor" ,
config : {
trigger : "onInsert" , // or "onUpdate", "always", "manual"
generateEmbeddings : true , // Auto-trigger embeddings after processing
queue : await ExuluQueues . register ( "processing" ),
timeoutInSeconds : 300 ,
retries : 2 ,
backoff : {
type : "exponential" ,
delay : 2000
}
},
filter : async ({ item , user }) => {
// Optional: Filter which items to process
return item . document_s3key !== undefined ;
},
execute : async ({ item , utils , exuluConfig }) => {
// Transform the item
const text = await utils . storage . extractText ( item . document_s3key );
return {
... item ,
content: text ,
textlength: text . length
};
}
}
rateLimit
Rate limiting rules for API access to this context
rateLimit : {
points : 100 , // Number of requests
duration : 60 , // Time window in seconds
blockDuration : 60 // Block duration after exceeding limit
}
queryRewriter
queryRewriter
(query: string) => Promise<string>
Function that rewrites queries before search to improve results
queryRewriter : async ( query : string ) => {
// Use an LLM to expand or clarify the query
const response = await openai . chat . completions . create ({
model: "gpt-4" ,
messages: [
{
role: "system" ,
content: "Expand this query to improve search results"
},
{
role: "user" ,
content: query
}
]
});
return response . choices [ 0 ]. message . content ;
}
resultReranker
resultReranker
(results: any[]) => Promise<any[]>
Function that reranks search results based on custom logic or a reranker model
resultReranker : async ( results ) => {
// Use a reranker to improve result ordering
const reranked = await cohereReranker . rerank ({
query: results [ 0 ]. query ,
documents: results . map ( r => r . chunk_content )
});
return reranked . results . map ( r => results [ r . index ]);
}
Configuration object
Additional configuration options for search behavior
calculateVectors
configuration.calculateVectors
'manual' | 'onUpdate' | 'onInsert' | 'always'
When to automatically generate embeddings for items (default: "manual")
configuration : {
calculateVectors : "onInsert" // Generate embeddings when items are created
}
manual
onInsert
onUpdate
always
Never auto-generate embeddings. You must call embeddings.generate.one() or embeddings.generate.all() manually.
Generate embeddings when new items are created
Generate embeddings when items are updated
Generate embeddings on both insert and update
maxRetrievalResults
configuration.maxRetrievalResults
Maximum number of results to return from search queries (default: 10)
configuration : {
maxRetrievalResults : 20
}
defaultRightsMode
configuration.defaultRightsMode
'private' | 'public' | 'restricted'
Default access control mode for new items (default: "private")
configuration : {
defaultRightsMode : "public"
}
configuration.enableAsTool
Whether to automatically expose this context as a tool for agents (default: true)
configuration : {
enableAsTool : true // Agents can query this context
}
When enabled, agents receive a tool called {context_name}_context_search that they can use to query this context.
cutoffs
Minimum relevance scores for different search methods
configuration : {
cutoffs : {
cosineDistance : 0.7 , // Min similarity for semantic search (0-1)
tsvector : 0.5 , // Min score for keyword search
hybrid : 0.6 // Min score for hybrid search
}
}
Results below these thresholds are filtered out.
Number of surrounding chunks to include with each result
configuration : {
expand : {
before : 1 , // Include 1 chunk before the matched chunk
after : 2 // Include 2 chunks after the matched chunk
}
}
This provides more context around matched chunks, improving the agent’s understanding.
language
Language for full-text search indexing (default: "english")
configuration : {
language : "german" // Use German text search configuration
}
This affects stemming and stop words in keyword search.
Complete example
import {
ExuluContext ,
ExuluEmbedder ,
ExuluQueues
} from "@exulu/backend" ;
const embedder = new ExuluEmbedder ({
id: "openai_ada" ,
name: "OpenAI Ada" ,
provider: "openai" ,
model: "text-embedding-3-small" ,
vectorDimensions: 1536 ,
template: "Title: {{title}} \n Category: {{category}} \n\n {{content}}"
});
const docsContext = new ExuluContext ({
id: "product_docs" ,
name: "Product Documentation" ,
description: "Comprehensive product docs including guides, API references, and tutorials" ,
active: true ,
fields: [
{
name: "title" ,
type: "text" ,
required: true ,
index: true
},
{
name: "content" ,
type: "longtext" ,
required: true
},
{
name: "category" ,
type: "text" ,
enumValues: [ "guide" , "api" , "tutorial" , "reference" ],
index: true
},
{
name: "url" ,
type: "text" ,
unique: true
},
{
name: "last_updated" ,
type: "timestamp"
},
{
name: "metadata" ,
type: "json"
}
],
embedder: embedder ,
processor: {
name: "Markdown Processor" ,
config: {
trigger: "onInsert" ,
generateEmbeddings: true ,
queue: await ExuluQueues . register ( "doc_processing" )
},
execute : async ({ item }) => {
// Process markdown, extract headings, etc.
const processed = processMarkdown ( item . content );
return {
... item ,
content: processed . text ,
metadata: { headings: processed . headings }
};
}
},
sources: [
{
id: "github_docs" ,
name: "GitHub Documentation" ,
description: "Sync docs from GitHub repository" ,
config: {
schedule: "0 */4 * * *" , // Every 4 hours
queue: await ExuluQueues . register ( "github_sync" ),
retries: 3 ,
backoff: {
type: "exponential" ,
delay: 2000
}
},
execute : async ({ exuluConfig }) => {
const docs = await fetchGitHubDocs ();
return docs . map ( doc => ({
external_id: doc . path ,
name: doc . title ,
content: doc . content ,
category: doc . category ,
url: doc . url ,
last_updated: doc . updatedAt
}));
}
}
],
rateLimit: {
points: 100 ,
duration: 60 ,
blockDuration: 60
},
queryRewriter : async ( query ) => {
// Expand query with LLM
return expandQuery ( query );
},
resultReranker : async ( results ) => {
// Rerank with Cohere
return rerankResults ( results );
},
configuration: {
calculateVectors: "onInsert" ,
maxRetrievalResults: 15 ,
defaultRightsMode: "public" ,
enableAsTool: true ,
cutoffs: {
cosineDistance: 0.65 ,
tsvector: 0.5 ,
hybrid: 0.6
},
expand: {
before: 1 ,
after: 2
},
language: "english"
}
});
Field type reference
Short text field (VARCHAR). Use for titles, names, categories, etc.
Long text field (TEXT). Use for descriptions, articles, documentation content.
Floating point number (DOUBLE PRECISION)
Whole number (INTEGER)
Precise decimal number (DECIMAL)
True/false value (BOOLEAN)
Date without time (DATE)
Date with time (TIMESTAMP)
JSON object or array (JSONB)
S3 file reference. Creates a {field_name}_s3key column that stores the S3 object key.
Next steps